Fix scsi sector size confusion (Blue Swirl).

Fix short TOC read.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1942 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2006-05-26 16:46:55 +00:00
parent 0aff66b5c8
commit 7c22dd5216

View File

@ -31,10 +31,13 @@ struct SCSIDevice
int command;
uint32_t tag;
BlockDriverState *bdrv;
int sector_size;
/* The qemu block layer uses a fixed 512 byte sector size.
This is the number of 512 byte blocks in a single scsi sector. */
int cluster_size;
/* When transfering data buf_pos and buf_len contain a partially
transferred block of data (or response to a command), and
sector/sector_count identify any remaining sectors. */
sector/sector_count identify any remaining sectors.
Both sector and sector_count are in terms of qemu 512 byte blocks. */
/* ??? We should probably keep track of whether the data trasfer is
a read or a write. Currently we rely on the host getting it right. */
int sector;
@ -42,7 +45,7 @@ struct SCSIDevice
int buf_pos;
int buf_len;
int sense;
char buf[2048];
char buf[512];
scsi_completionfn completion;
void *opaque;
};
@ -75,24 +78,24 @@ int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
s->buf_pos = 0;
}
n = len / s->sector_size;
n = len / 512;
if (n > s->sector_count)
n = s->sector_count;
if (n != 0) {
bdrv_read(s->bdrv, s->sector, data, n);
data += n * s->sector_size;
len -= n * s->sector_size;
data += n * 512;
len -= n * 512;
s->sector += n;
s->sector_count -= n;
}
if (len && s->sector_count) {
bdrv_read(s->bdrv, s->sector, s->buf, 1);
bdrv_read(s->bdrv, s->sector, s->buf, 512);
s->sector++;
s->sector_count--;
s->buf_pos = 0;
s->buf_len = s->sector_size;
s->buf_len = 512;
/* Recurse to complete the partial read. */
return scsi_read_data(s, data, len);
}
@ -120,8 +123,8 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
if (s->sector_count == 0)
return 1;
if (s->buf_len != 0 || len < s->sector_size) {
n = s->sector_size - s->buf_len;
if (s->buf_len != 0 || len < 512) {
n = 512 - s->buf_len;
if (n > len)
n = len;
@ -129,7 +132,7 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
data += n;
s->buf_len += n;
len -= n;
if (s->buf_len == s->sector_size) {
if (s->buf_len == 512) {
/* A full sector has been accumulated. Write it to disk. */
bdrv_write(s->bdrv, s->sector, s->buf, 1);
s->buf_len = 0;
@ -138,19 +141,19 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
}
}
n = len / s->sector_size;
n = len / 512;
if (n > s->sector_count)
n = s->sector_count;
if (n != 0) {
bdrv_write(s->bdrv, s->sector, data, n);
data += n * s->sector_size;
len -= n * s->sector_size;
data += n * 512;
len -= n * 512;
s->sector += n;
s->sector_count -= n;
}
if (len >= s->sector_size)
if (len >= 512)
return 1;
if (len && s->sector_count) {
@ -296,26 +299,26 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
s->buf[3] = nb_sectors & 0xff;
s->buf[4] = 0;
s->buf[5] = 0;
s->buf[6] = s->sector_size >> 8;
s->buf[7] = s->sector_size & 0xff;
s->buf[6] = s->cluster_size * 2;
s->buf[7] = 0;
s->buf_len = 8;
break;
case 0x08:
case 0x28:
DPRINTF("Read (sector %d, count %d)\n", lba, len);
s->sector = lba;
s->sector_count = len;
s->sector = lba * s->cluster_size;
s->sector_count = len * s->cluster_size;
break;
case 0x0a:
case 0x2a:
DPRINTF("Write (sector %d, count %d)\n", lba, len);
s->sector = lba;
s->sector_count = len;
s->sector = lba * s->cluster_size;
s->sector_count = len * s->cluster_size;
is_write = 1;
break;
case 0x43:
{
int start_track, format, msf;
int start_track, format, msf, toclen;
msf = buf[1] & 2;
format = buf[2] & 0xf;
@ -324,31 +327,31 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
switch(format) {
case 0:
len = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
if (len < 0)
goto error_cmd;
s->buf_len = len;
toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
break;
case 1:
/* multi session : only a single session defined */
toclen = 12;
memset(s->buf, 0, 12);
s->buf[1] = 0x0a;
s->buf[2] = 0x01;
s->buf[3] = 0x01;
s->buf_len = 12;
break;
case 2:
len = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
if (len < 0)
goto error_cmd;
s->buf_len = len;
toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
break;
default:
error_cmd:
DPRINTF("Read TOC error\n");
goto fail;
goto error_cmd;
}
break;
if (toclen > 0) {
if (len > toclen)
len = toclen;
s->buf_len = len;
break;
}
error_cmd:
DPRINTF("Read TOC error\n");
goto fail;
}
case 0x56:
DPRINTF("Reserve(10)\n");
@ -377,7 +380,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
if (s->sector_count == 0 && s->buf_len == 0) {
scsi_command_complete(s, SENSE_NO_SENSE);
}
len = s->sector_count * s->sector_size + s->buf_len;
len = s->sector_count * 512 + s->buf_len;
return is_write ? -len : len;
}
@ -398,9 +401,9 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
s->completion = completion;
s->opaque = opaque;
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
s->sector_size = 2048;
s->cluster_size = 4;
} else {
s->sector_size = 512;
s->cluster_size = 1;
}
return s;