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