Commit 7c22dd5216a7c1ff941e37bc30a6ade6e1370ca1

Authored by pbrook
1 parent 0aff66b5

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
Showing 1 changed file with 41 additions and 38 deletions
hw/scsi-disk.c
@@ -31,10 +31,13 @@ struct SCSIDevice @@ -31,10 +31,13 @@ struct SCSIDevice
31 int command; 31 int command;
32 uint32_t tag; 32 uint32_t tag;
33 BlockDriverState *bdrv; 33 BlockDriverState *bdrv;
34 - int sector_size; 34 + /* The qemu block layer uses a fixed 512 byte sector size.
  35 + This is the number of 512 byte blocks in a single scsi sector. */
  36 + int cluster_size;
35 /* When transfering data buf_pos and buf_len contain a partially 37 /* When transfering data buf_pos and buf_len contain a partially
36 transferred block of data (or response to a command), and 38 transferred block of data (or response to a command), and
37 - sector/sector_count identify any remaining sectors. */ 39 + sector/sector_count identify any remaining sectors.
  40 + Both sector and sector_count are in terms of qemu 512 byte blocks. */
38 /* ??? We should probably keep track of whether the data trasfer is 41 /* ??? We should probably keep track of whether the data trasfer is
39 a read or a write. Currently we rely on the host getting it right. */ 42 a read or a write. Currently we rely on the host getting it right. */
40 int sector; 43 int sector;
@@ -42,7 +45,7 @@ struct SCSIDevice @@ -42,7 +45,7 @@ struct SCSIDevice
42 int buf_pos; 45 int buf_pos;
43 int buf_len; 46 int buf_len;
44 int sense; 47 int sense;
45 - char buf[2048]; 48 + char buf[512];
46 scsi_completionfn completion; 49 scsi_completionfn completion;
47 void *opaque; 50 void *opaque;
48 }; 51 };
@@ -75,24 +78,24 @@ int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len) @@ -75,24 +78,24 @@ int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
75 s->buf_pos = 0; 78 s->buf_pos = 0;
76 } 79 }
77 80
78 - n = len / s->sector_size; 81 + n = len / 512;
79 if (n > s->sector_count) 82 if (n > s->sector_count)
80 n = s->sector_count; 83 n = s->sector_count;
81 84
82 if (n != 0) { 85 if (n != 0) {
83 bdrv_read(s->bdrv, s->sector, data, n); 86 bdrv_read(s->bdrv, s->sector, data, n);
84 - data += n * s->sector_size;  
85 - len -= n * s->sector_size; 87 + data += n * 512;
  88 + len -= n * 512;
86 s->sector += n; 89 s->sector += n;
87 s->sector_count -= n; 90 s->sector_count -= n;
88 } 91 }
89 92
90 if (len && s->sector_count) { 93 if (len && s->sector_count) {
91 - bdrv_read(s->bdrv, s->sector, s->buf, 1); 94 + bdrv_read(s->bdrv, s->sector, s->buf, 512);
92 s->sector++; 95 s->sector++;
93 s->sector_count--; 96 s->sector_count--;
94 s->buf_pos = 0; 97 s->buf_pos = 0;
95 - s->buf_len = s->sector_size; 98 + s->buf_len = 512;
96 /* Recurse to complete the partial read. */ 99 /* Recurse to complete the partial read. */
97 return scsi_read_data(s, data, len); 100 return scsi_read_data(s, data, len);
98 } 101 }
@@ -120,8 +123,8 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len) @@ -120,8 +123,8 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
120 if (s->sector_count == 0) 123 if (s->sector_count == 0)
121 return 1; 124 return 1;
122 125
123 - if (s->buf_len != 0 || len < s->sector_size) {  
124 - n = s->sector_size - s->buf_len; 126 + if (s->buf_len != 0 || len < 512) {
  127 + n = 512 - s->buf_len;
125 if (n > len) 128 if (n > len)
126 n = len; 129 n = len;
127 130
@@ -129,7 +132,7 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len) @@ -129,7 +132,7 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
129 data += n; 132 data += n;
130 s->buf_len += n; 133 s->buf_len += n;
131 len -= n; 134 len -= n;
132 - if (s->buf_len == s->sector_size) { 135 + if (s->buf_len == 512) {
133 /* A full sector has been accumulated. Write it to disk. */ 136 /* A full sector has been accumulated. Write it to disk. */
134 bdrv_write(s->bdrv, s->sector, s->buf, 1); 137 bdrv_write(s->bdrv, s->sector, s->buf, 1);
135 s->buf_len = 0; 138 s->buf_len = 0;
@@ -138,19 +141,19 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len) @@ -138,19 +141,19 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
138 } 141 }
139 } 142 }
140 143
141 - n = len / s->sector_size; 144 + n = len / 512;
142 if (n > s->sector_count) 145 if (n > s->sector_count)
143 n = s->sector_count; 146 n = s->sector_count;
144 147
145 if (n != 0) { 148 if (n != 0) {
146 bdrv_write(s->bdrv, s->sector, data, n); 149 bdrv_write(s->bdrv, s->sector, data, n);
147 - data += n * s->sector_size;  
148 - len -= n * s->sector_size; 150 + data += n * 512;
  151 + len -= n * 512;
149 s->sector += n; 152 s->sector += n;
150 s->sector_count -= n; 153 s->sector_count -= n;
151 } 154 }
152 155
153 - if (len >= s->sector_size) 156 + if (len >= 512)
154 return 1; 157 return 1;
155 158
156 if (len && s->sector_count) { 159 if (len && s->sector_count) {
@@ -296,26 +299,26 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) @@ -296,26 +299,26 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
296 s->buf[3] = nb_sectors & 0xff; 299 s->buf[3] = nb_sectors & 0xff;
297 s->buf[4] = 0; 300 s->buf[4] = 0;
298 s->buf[5] = 0; 301 s->buf[5] = 0;
299 - s->buf[6] = s->sector_size >> 8;  
300 - s->buf[7] = s->sector_size & 0xff; 302 + s->buf[6] = s->cluster_size * 2;
  303 + s->buf[7] = 0;
301 s->buf_len = 8; 304 s->buf_len = 8;
302 break; 305 break;
303 case 0x08: 306 case 0x08:
304 case 0x28: 307 case 0x28:
305 DPRINTF("Read (sector %d, count %d)\n", lba, len); 308 DPRINTF("Read (sector %d, count %d)\n", lba, len);
306 - s->sector = lba;  
307 - s->sector_count = len; 309 + s->sector = lba * s->cluster_size;
  310 + s->sector_count = len * s->cluster_size;
308 break; 311 break;
309 case 0x0a: 312 case 0x0a:
310 case 0x2a: 313 case 0x2a:
311 DPRINTF("Write (sector %d, count %d)\n", lba, len); 314 DPRINTF("Write (sector %d, count %d)\n", lba, len);
312 - s->sector = lba;  
313 - s->sector_count = len; 315 + s->sector = lba * s->cluster_size;
  316 + s->sector_count = len * s->cluster_size;
314 is_write = 1; 317 is_write = 1;
315 break; 318 break;
316 case 0x43: 319 case 0x43:
317 { 320 {
318 - int start_track, format, msf; 321 + int start_track, format, msf, toclen;
319 322
320 msf = buf[1] & 2; 323 msf = buf[1] & 2;
321 format = buf[2] & 0xf; 324 format = buf[2] & 0xf;
@@ -324,31 +327,31 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) @@ -324,31 +327,31 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
324 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1); 327 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
325 switch(format) { 328 switch(format) {
326 case 0: 329 case 0:
327 - len = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);  
328 - if (len < 0)  
329 - goto error_cmd;  
330 - s->buf_len = len; 330 + toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
331 break; 331 break;
332 case 1: 332 case 1:
333 /* multi session : only a single session defined */ 333 /* multi session : only a single session defined */
  334 + toclen = 12;
334 memset(s->buf, 0, 12); 335 memset(s->buf, 0, 12);
335 s->buf[1] = 0x0a; 336 s->buf[1] = 0x0a;
336 s->buf[2] = 0x01; 337 s->buf[2] = 0x01;
337 s->buf[3] = 0x01; 338 s->buf[3] = 0x01;
338 - s->buf_len = 12;  
339 break; 339 break;
340 case 2: 340 case 2:
341 - len = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);  
342 - if (len < 0)  
343 - goto error_cmd;  
344 - s->buf_len = len; 341 + toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
345 break; 342 break;
346 default: 343 default:
347 - error_cmd:  
348 - DPRINTF("Read TOC error\n");  
349 - goto fail; 344 + goto error_cmd;
  345 + }
  346 + if (toclen > 0) {
  347 + if (len > toclen)
  348 + len = toclen;
  349 + s->buf_len = len;
  350 + break;
350 } 351 }
351 - break; 352 + error_cmd:
  353 + DPRINTF("Read TOC error\n");
  354 + goto fail;
352 } 355 }
353 case 0x56: 356 case 0x56:
354 DPRINTF("Reserve(10)\n"); 357 DPRINTF("Reserve(10)\n");
@@ -377,7 +380,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) @@ -377,7 +380,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
377 if (s->sector_count == 0 && s->buf_len == 0) { 380 if (s->sector_count == 0 && s->buf_len == 0) {
378 scsi_command_complete(s, SENSE_NO_SENSE); 381 scsi_command_complete(s, SENSE_NO_SENSE);
379 } 382 }
380 - len = s->sector_count * s->sector_size + s->buf_len; 383 + len = s->sector_count * 512 + s->buf_len;
381 return is_write ? -len : len; 384 return is_write ? -len : len;
382 } 385 }
383 386
@@ -398,9 +401,9 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, @@ -398,9 +401,9 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
398 s->completion = completion; 401 s->completion = completion;
399 s->opaque = opaque; 402 s->opaque = opaque;
400 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { 403 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
401 - s->sector_size = 2048; 404 + s->cluster_size = 4;
402 } else { 405 } else {
403 - s->sector_size = 512; 406 + s->cluster_size = 1;
404 } 407 }
405 408
406 return s; 409 return s;