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 31 int command;
32 32 uint32_t tag;
33 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 37 /* When transfering data buf_pos and buf_len contain a partially
36 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 41 /* ??? We should probably keep track of whether the data trasfer is
39 42 a read or a write. Currently we rely on the host getting it right. */
40 43 int sector;
... ... @@ -42,7 +45,7 @@ struct SCSIDevice
42 45 int buf_pos;
43 46 int buf_len;
44 47 int sense;
45   - char buf[2048];
  48 + char buf[512];
46 49 scsi_completionfn completion;
47 50 void *opaque;
48 51 };
... ... @@ -75,24 +78,24 @@ int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
75 78 s->buf_pos = 0;
76 79 }
77 80  
78   - n = len / s->sector_size;
  81 + n = len / 512;
79 82 if (n > s->sector_count)
80 83 n = s->sector_count;
81 84  
82 85 if (n != 0) {
83 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 89 s->sector += n;
87 90 s->sector_count -= n;
88 91 }
89 92  
90 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 95 s->sector++;
93 96 s->sector_count--;
94 97 s->buf_pos = 0;
95   - s->buf_len = s->sector_size;
  98 + s->buf_len = 512;
96 99 /* Recurse to complete the partial read. */
97 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 123 if (s->sector_count == 0)
121 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 128 if (n > len)
126 129 n = len;
127 130  
... ... @@ -129,7 +132,7 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
129 132 data += n;
130 133 s->buf_len += n;
131 134 len -= n;
132   - if (s->buf_len == s->sector_size) {
  135 + if (s->buf_len == 512) {
133 136 /* A full sector has been accumulated. Write it to disk. */
134 137 bdrv_write(s->bdrv, s->sector, s->buf, 1);
135 138 s->buf_len = 0;
... ... @@ -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 145 if (n > s->sector_count)
143 146 n = s->sector_count;
144 147  
145 148 if (n != 0) {
146 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 152 s->sector += n;
150 153 s->sector_count -= n;
151 154 }
152 155  
153   - if (len >= s->sector_size)
  156 + if (len >= 512)
154 157 return 1;
155 158  
156 159 if (len && s->sector_count) {
... ... @@ -296,26 +299,26 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
296 299 s->buf[3] = nb_sectors & 0xff;
297 300 s->buf[4] = 0;
298 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 304 s->buf_len = 8;
302 305 break;
303 306 case 0x08:
304 307 case 0x28:
305 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 311 break;
309 312 case 0x0a:
310 313 case 0x2a:
311 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 317 is_write = 1;
315 318 break;
316 319 case 0x43:
317 320 {
318   - int start_track, format, msf;
  321 + int start_track, format, msf, toclen;
319 322  
320 323 msf = buf[1] & 2;
321 324 format = buf[2] & 0xf;
... ... @@ -324,31 +327,31 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
324 327 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
325 328 switch(format) {
326 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 331 break;
332 332 case 1:
333 333 /* multi session : only a single session defined */
  334 + toclen = 12;
334 335 memset(s->buf, 0, 12);
335 336 s->buf[1] = 0x0a;
336 337 s->buf[2] = 0x01;
337 338 s->buf[3] = 0x01;
338   - s->buf_len = 12;
339 339 break;
340 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 342 break;
346 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 356 case 0x56:
354 357 DPRINTF("Reserve(10)\n");
... ... @@ -377,7 +380,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
377 380 if (s->sector_count == 0 && s->buf_len == 0) {
378 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 384 return is_write ? -len : len;
382 385 }
383 386  
... ... @@ -398,9 +401,9 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
398 401 s->completion = completion;
399 402 s->opaque = opaque;
400 403 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
401   - s->sector_size = 2048;
  404 + s->cluster_size = 4;
402 405 } else {
403   - s->sector_size = 512;
  406 + s->cluster_size = 1;
404 407 }
405 408  
406 409 return s;
... ...