Commit 17acfe326ce2038033934485145ddd2390337986

Authored by pbrook
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,7 +213,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
213 cmdlen = 12; 213 cmdlen = 12;
214 break; 214 break;
215 default: 215 default:
216 - BADF("Unsupported command length\n"); 216 + BADF("Unsupported command length, command %x\n", s->command);
217 goto fail; 217 goto fail;
218 } 218 }
219 #ifdef DEBUG_SCSI 219 #ifdef DEBUG_SCSI
@@ -260,7 +260,9 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) @@ -260,7 +260,9 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
260 } 260 }
261 memcpy(&s->buf[8], "QEMU ", 8); 261 memcpy(&s->buf[8], "QEMU ", 8);
262 memcpy(&s->buf[32], QEMU_VERSION, 4); 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 s->buf[3] = 2; /* Format 2 */ 266 s->buf[3] = 2; /* Format 2 */
265 s->buf[4] = 32; 267 s->buf[4] = 32;
266 s->buf_len = 36; 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,27 +279,69 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
277 break; 279 break;
278 case 0x1a: 280 case 0x1a:
279 case 0x5a: 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 s->buf[1] = 0; /* Default media type. */ 290 s->buf[1] = 0; /* Default media type. */
291 - s->buf[2] = 0; /* Write enabled. */  
292 s->buf[3] = 0; /* Block descriptor length. */ 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 break; 345 break;
302 case 0x25: 346 case 0x25:
303 DPRINTF("Read Capacity\n"); 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,6 +412,14 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
368 DPRINTF("Read TOC error\n"); 412 DPRINTF("Read TOC error\n");
369 goto fail; 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 case 0x56: 423 case 0x56:
372 DPRINTF("Reserve(10)\n"); 424 DPRINTF("Reserve(10)\n");
373 if (buf[1] & 3) 425 if (buf[1] & 3)