Commit 7c22dd5216a7c1ff941e37bc30a6ade6e1370ca1
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; | ... | ... |