Revision 1d4db89c hw/scsi-disk.c
b/hw/scsi-disk.c | ||
---|---|---|
9 | 9 |
* This code is licenced under the LGPL. |
10 | 10 |
* |
11 | 11 |
* Note that this file only handles the SCSI architecture model and device |
12 |
* commands. Emultion of interface/link layer protocols is handled by |
|
13 |
* the host adapter emulation.
|
|
12 |
* commands. Emulation of interface/link layer protocols is handled by
|
|
13 |
* the host adapter emulator.
|
|
14 | 14 |
*/ |
15 | 15 |
|
16 | 16 |
//#define DEBUG_SCSI |
... | ... | |
362 | 362 |
break; |
363 | 363 |
case 0x12: |
364 | 364 |
DPRINTF("Inquiry (len %d)\n", len); |
365 |
if (len < 36) { |
|
366 |
BADF("Inquiry buffer too small (%d)\n", len); |
|
365 |
if (buf[1] & 0x2) { |
|
366 |
/* Command support data - optional, not implemented */ |
|
367 |
BADF("optional INQUIRY command support request not implemented\n"); |
|
368 |
goto fail; |
|
369 |
} |
|
370 |
else if (buf[1] & 0x1) { |
|
371 |
/* Vital product data */ |
|
372 |
uint8_t page_code = buf[2]; |
|
373 |
if (len < 4) { |
|
374 |
BADF("Error: Inquiry (EVPD[%02X]) buffer size %d is " |
|
375 |
"less than 4\n", page_code, len); |
|
376 |
goto fail; |
|
377 |
} |
|
378 |
|
|
379 |
switch (page_code) { |
|
380 |
case 0x00: |
|
381 |
{ |
|
382 |
/* Supported page codes, mandatory */ |
|
383 |
DPRINTF("Inquiry EVPD[Supported pages] " |
|
384 |
"buffer size %d\n", len); |
|
385 |
|
|
386 |
r->buf_len = 0; |
|
387 |
|
|
388 |
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { |
|
389 |
outbuf[r->buf_len++] = 5; |
|
390 |
} else { |
|
391 |
outbuf[r->buf_len++] = 0; |
|
392 |
} |
|
393 |
|
|
394 |
outbuf[r->buf_len++] = 0x00; // this page |
|
395 |
outbuf[r->buf_len++] = 0x00; |
|
396 |
outbuf[r->buf_len++] = 3; // number of pages |
|
397 |
outbuf[r->buf_len++] = 0x00; // list of supported pages (this page) |
|
398 |
outbuf[r->buf_len++] = 0x80; // unit serial number |
|
399 |
outbuf[r->buf_len++] = 0x83; // device identification |
|
400 |
} |
|
401 |
break; |
|
402 |
case 0x80: |
|
403 |
{ |
|
404 |
/* Device serial number, optional */ |
|
405 |
if (len < 4) { |
|
406 |
BADF("Error: EVPD[Serial number] Inquiry buffer " |
|
407 |
"size %d too small, %d needed\n", len, 4); |
|
408 |
goto fail; |
|
409 |
} |
|
410 |
|
|
411 |
DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len); |
|
412 |
|
|
413 |
r->buf_len = 0; |
|
414 |
|
|
415 |
/* Supported page codes */ |
|
416 |
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { |
|
417 |
outbuf[r->buf_len++] = 5; |
|
418 |
} else { |
|
419 |
outbuf[r->buf_len++] = 0; |
|
420 |
} |
|
421 |
|
|
422 |
outbuf[r->buf_len++] = 0x80; // this page |
|
423 |
outbuf[r->buf_len++] = 0x00; |
|
424 |
outbuf[r->buf_len++] = 0x01; // 1 byte data follow |
|
425 |
|
|
426 |
outbuf[r->buf_len++] = '0'; // 1 byte data follow |
|
427 |
} |
|
428 |
|
|
429 |
break; |
|
430 |
case 0x83: |
|
431 |
{ |
|
432 |
/* Device identification page, mandatory */ |
|
433 |
int max_len = 255 - 8; |
|
434 |
int id_len = strlen(bdrv_get_device_name(s->bdrv)); |
|
435 |
if (id_len > max_len) |
|
436 |
id_len = max_len; |
|
437 |
|
|
438 |
DPRINTF("Inquiry EVPD[Device identification] " |
|
439 |
"buffer size %d\n", len); |
|
440 |
r->buf_len = 0; |
|
441 |
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { |
|
442 |
outbuf[r->buf_len++] = 5; |
|
443 |
} else { |
|
444 |
outbuf[r->buf_len++] = 0; |
|
445 |
} |
|
446 |
|
|
447 |
outbuf[r->buf_len++] = 0x83; // this page |
|
448 |
outbuf[r->buf_len++] = 0x00; |
|
449 |
outbuf[r->buf_len++] = 3 + id_len; |
|
450 |
|
|
451 |
outbuf[r->buf_len++] = 0x2; // ASCII |
|
452 |
outbuf[r->buf_len++] = 0; // not officially assigned |
|
453 |
outbuf[r->buf_len++] = 0; // reserved |
|
454 |
outbuf[r->buf_len++] = id_len; // length of data following |
|
455 |
|
|
456 |
memcpy(&outbuf[r->buf_len], |
|
457 |
bdrv_get_device_name(s->bdrv), id_len); |
|
458 |
r->buf_len += id_len; |
|
459 |
} |
|
460 |
break; |
|
461 |
default: |
|
462 |
BADF("Error: unsupported Inquiry (EVPD[%02X]) " |
|
463 |
"buffer size %d\n", page_code, len); |
|
464 |
goto fail; |
|
465 |
} |
|
466 |
/* done with EVPD */ |
|
467 |
break; |
|
468 |
} |
|
469 |
else { |
|
470 |
/* Standard INQUIRY data */ |
|
471 |
if (buf[2] != 0) { |
|
472 |
BADF("Error: Inquiry (STANDARD) page or code " |
|
473 |
"is non-zero [%02X]\n", buf[2]); |
|
474 |
goto fail; |
|
475 |
} |
|
476 |
|
|
477 |
/* PAGE CODE == 0 */ |
|
478 |
if (len < 5) { |
|
479 |
BADF("Error: Inquiry (STANDARD) buffer size %d " |
|
480 |
"is less than 5\n", len); |
|
481 |
goto fail; |
|
482 |
} |
|
483 |
|
|
484 |
if (len < 36) { |
|
485 |
BADF("Error: Inquiry (STANDARD) buffer size %d " |
|
486 |
"is less than 36 (TODO: only 5 required)\n", len); |
|
487 |
} |
|
367 | 488 |
} |
368 | 489 |
memset(outbuf, 0, 36); |
369 | 490 |
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { |
Also available in: Unified diff