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