Commit 1d4db89c09264463ec8d388e84b665f90763b29d

Authored by balrog
1 parent b5a23ad4

Implement more INQUIRY command replies for scsi disk (Igor Kovalenko).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3955 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 125 additions and 4 deletions
hw/scsi-disk.c
... ... @@ -9,8 +9,8 @@
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,8 +362,129 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
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) {
... ...