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