Commit 17acfe326ce2038033934485145ddd2390337986
1 parent
9f149aa9
More SCSI commands (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1948 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
72 additions
and
20 deletions
hw/scsi-disk.c
| ... | ... | @@ -213,7 +213,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) |
| 213 | 213 | cmdlen = 12; |
| 214 | 214 | break; |
| 215 | 215 | default: |
| 216 | - BADF("Unsupported command length\n"); | |
| 216 | + BADF("Unsupported command length, command %x\n", s->command); | |
| 217 | 217 | goto fail; |
| 218 | 218 | } |
| 219 | 219 | #ifdef DEBUG_SCSI |
| ... | ... | @@ -260,7 +260,9 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) |
| 260 | 260 | } |
| 261 | 261 | memcpy(&s->buf[8], "QEMU ", 8); |
| 262 | 262 | memcpy(&s->buf[32], QEMU_VERSION, 4); |
| 263 | - s->buf[2] = 3; /* SCSI-3 */ | |
| 263 | + /* Identify device as SCSI-3 rev 1. | |
| 264 | + Some later commands are also implemented. */ | |
| 265 | + s->buf[2] = 3; | |
| 264 | 266 | s->buf[3] = 2; /* Format 2 */ |
| 265 | 267 | s->buf[4] = 32; |
| 266 | 268 | s->buf_len = 36; |
| ... | ... | @@ -277,27 +279,69 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) |
| 277 | 279 | break; |
| 278 | 280 | case 0x1a: |
| 279 | 281 | case 0x5a: |
| 280 | - DPRINTF("Mode Sense (page %d, len %d)\n", buf[2], len); | |
| 281 | - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { | |
| 282 | - memset(s->buf, 0, 4); | |
| 283 | - s->buf[0] = 4; /* Mode data length. */ | |
| 284 | - s->buf[1] = 0; /* Default media type. */ | |
| 285 | - s->buf[2] = 0x80; /* Readonly. */ | |
| 286 | - s->buf[3] = 0; /* Block descriptor length. */ | |
| 287 | - } else { | |
| 288 | - memset(s->buf, 0, 0x16); | |
| 289 | - s->buf[0] = 0x16; /* Mode data length (4 + 0x12). */ | |
| 282 | + { | |
| 283 | + char *p; | |
| 284 | + int page; | |
| 285 | + | |
| 286 | + page = buf[2] & 0x3f; | |
| 287 | + DPRINTF("Mode Sense (page %d, len %d)\n", page, len); | |
| 288 | + p = s->buf; | |
| 289 | + memset(p, 0, 4); | |
| 290 | 290 | s->buf[1] = 0; /* Default media type. */ |
| 291 | - s->buf[2] = 0; /* Write enabled. */ | |
| 292 | 291 | s->buf[3] = 0; /* Block descriptor length. */ |
| 293 | - /* Caching page. */ | |
| 294 | - s->buf[4 + 0] = 8; | |
| 295 | - s->buf[4 + 1] = 0x12; | |
| 296 | - s->buf[4 + 2] = 4; /* WCE */ | |
| 297 | - if (len > 0x16) | |
| 298 | - len = 0x16; | |
| 292 | + if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { | |
| 293 | + s->buf[2] = 0x80; /* Readonly. */ | |
| 294 | + } | |
| 295 | + p += 4; | |
| 296 | + if ((page == 8 || page == 0x3f)) { | |
| 297 | + /* Caching page. */ | |
| 298 | + p[0] = 8; | |
| 299 | + p[1] = 0x12; | |
| 300 | + p[2] = 4; /* WCE */ | |
| 301 | + p += 19; | |
| 302 | + } | |
| 303 | + if ((page == 0x3f || page == 0x2a) | |
| 304 | + && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) { | |
| 305 | + /* CD Capabilities and Mechanical Status page. */ | |
| 306 | + p[0] = 0x2a; | |
| 307 | + p[1] = 0x14; | |
| 308 | + p[2] = 3; // CD-R & CD-RW read | |
| 309 | + p[3] = 0; // Writing not supported | |
| 310 | + p[4] = 0x7f; /* Audio, composite, digital out, | |
| 311 | + mode 2 form 1&2, multi session */ | |
| 312 | + p[5] = 0xff; /* CD DA, DA accurate, RW supported, | |
| 313 | + RW corrected, C2 errors, ISRC, | |
| 314 | + UPC, Bar code */ | |
| 315 | + p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0); | |
| 316 | + /* Locking supported, jumper present, eject, tray */ | |
| 317 | + p[7] = 0; /* no volume & mute control, no | |
| 318 | + changer */ | |
| 319 | + p[8] = (50 * 176) >> 8; // 50x read speed | |
| 320 | + p[9] = (50 * 176) & 0xff; | |
| 321 | + p[10] = 0 >> 8; // No volume | |
| 322 | + p[11] = 0 & 0xff; | |
| 323 | + p[12] = 2048 >> 8; // 2M buffer | |
| 324 | + p[13] = 2048 & 0xff; | |
| 325 | + p[14] = (16 * 176) >> 8; // 16x read speed current | |
| 326 | + p[15] = (16 * 176) & 0xff; | |
| 327 | + p[18] = (16 * 176) >> 8; // 16x write speed | |
| 328 | + p[19] = (16 * 176) & 0xff; | |
| 329 | + p[20] = (16 * 176) >> 8; // 16x write speed current | |
| 330 | + p[21] = (16 * 176) & 0xff; | |
| 331 | + p += 21; | |
| 332 | + } | |
| 333 | + s->buf_len = p - s->buf; | |
| 334 | + s->buf[0] = s->buf_len - 4; | |
| 335 | + if (s->buf_len > len) | |
| 336 | + s->buf_len = len; | |
| 299 | 337 | } |
| 300 | - s->buf_len = len; | |
| 338 | + break; | |
| 339 | + case 0x1b: | |
| 340 | + DPRINTF("Start Stop Unit\n"); | |
| 341 | + break; | |
| 342 | + case 0x1e: | |
| 343 | + DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3); | |
| 344 | + bdrv_set_locked(s->bdrv, buf[4] & 1); | |
| 301 | 345 | break; |
| 302 | 346 | case 0x25: |
| 303 | 347 | DPRINTF("Read Capacity\n"); |
| ... | ... | @@ -368,6 +412,14 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) |
| 368 | 412 | DPRINTF("Read TOC error\n"); |
| 369 | 413 | goto fail; |
| 370 | 414 | } |
| 415 | + case 0x46: | |
| 416 | + DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len); | |
| 417 | + memset(s->buf, 0, 8); | |
| 418 | + /* ??? This shoud probably return much more information. For now | |
| 419 | + just return the basic header indicating the CD-ROM profile. */ | |
| 420 | + s->buf[7] = 8; // CD-ROM | |
| 421 | + s->buf_len = 8; | |
| 422 | + break; | |
| 371 | 423 | case 0x56: |
| 372 | 424 | DPRINTF("Reserve(10)\n"); |
| 373 | 425 | if (buf[1] & 3) | ... | ... |