Revision ebddfcbe hw/scsi-disk.c

b/hw/scsi-disk.c
440 440
    return buflen;
441 441
}
442 442

  
443
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
444
{
445
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
446
    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
447
    int cylinders, heads, secs;
448

  
449
    switch (page) {
450
    case 4: /* Rigid disk device geometry page. */
451
        p[0] = 4;
452
        p[1] = 0x16;
453
        /* if a geometry hint is available, use it */
454
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
455
        p[2] = (cylinders >> 16) & 0xff;
456
        p[3] = (cylinders >> 8) & 0xff;
457
        p[4] = cylinders & 0xff;
458
        p[5] = heads & 0xff;
459
        /* Write precomp start cylinder, disabled */
460
        p[6] = (cylinders >> 16) & 0xff;
461
        p[7] = (cylinders >> 8) & 0xff;
462
        p[8] = cylinders & 0xff;
463
        /* Reduced current start cylinder, disabled */
464
        p[9] = (cylinders >> 16) & 0xff;
465
        p[10] = (cylinders >> 8) & 0xff;
466
        p[11] = cylinders & 0xff;
467
        /* Device step rate [ns], 200ns */
468
        p[12] = 0;
469
        p[13] = 200;
470
        /* Landing zone cylinder */
471
        p[14] = 0xff;
472
        p[15] =  0xff;
473
        p[16] = 0xff;
474
        /* Medium rotation rate [rpm], 5400 rpm */
475
        p[20] = (5400 >> 8) & 0xff;
476
        p[21] = 5400 & 0xff;
477
        return 0x16;
478

  
479
    case 5: /* Flexible disk device geometry page. */
480
        p[0] = 5;
481
        p[1] = 0x1e;
482
        /* Transfer rate [kbit/s], 5Mbit/s */
483
        p[2] = 5000 >> 8;
484
        p[3] = 5000 & 0xff;
485
        /* if a geometry hint is available, use it */
486
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
487
        p[4] = heads & 0xff;
488
        p[5] = secs & 0xff;
489
        p[6] = s->cluster_size * 2;
490
        p[8] = (cylinders >> 8) & 0xff;
491
        p[9] = cylinders & 0xff;
492
        /* Write precomp start cylinder, disabled */
493
        p[10] = (cylinders >> 8) & 0xff;
494
        p[11] = cylinders & 0xff;
495
        /* Reduced current start cylinder, disabled */
496
        p[12] = (cylinders >> 8) & 0xff;
497
        p[13] = cylinders & 0xff;
498
        /* Device step rate [100us], 100us */
499
        p[14] = 0;
500
        p[15] = 1;
501
        /* Device step pulse width [us], 1us */
502
        p[16] = 1;
503
        /* Device head settle delay [100us], 100us */
504
        p[17] = 0;
505
        p[18] = 1;
506
        /* Motor on delay [0.1s], 0.1s */
507
        p[19] = 1;
508
        /* Motor off delay [0.1s], 0.1s */
509
        p[20] = 1;
510
        /* Medium rotation rate [rpm], 5400 rpm */
511
        p[28] = (5400 >> 8) & 0xff;
512
        p[29] = 5400 & 0xff;
513
        return 0x1e;
514

  
515
    case 8: /* Caching page.  */
516
        p[0] = 8;
517
        p[1] = 0x12;
518
        if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
519
            p[2] = 4; /* WCE */
520
        }
521
        return 20;
522

  
523
    case 0x2a: /* CD Capabilities and Mechanical Status page. */
524
        if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
525
            return 0;
526
        p[0] = 0x2a;
527
        p[1] = 0x14;
528
        p[2] = 3; // CD-R & CD-RW read
529
        p[3] = 0; // Writing not supported
530
        p[4] = 0x7f; /* Audio, composite, digital out,
531
                        mode 2 form 1&2, multi session */
532
        p[5] = 0xff; /* CD DA, DA accurate, RW supported,
533
                        RW corrected, C2 errors, ISRC,
534
                        UPC, Bar code */
535
        p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
536
        /* Locking supported, jumper present, eject, tray */
537
        p[7] = 0; /* no volume & mute control, no
538
                     changer */
539
        p[8] = (50 * 176) >> 8; // 50x read speed
540
        p[9] = (50 * 176) & 0xff;
541
        p[10] = 0 >> 8; // No volume
542
        p[11] = 0 & 0xff;
543
        p[12] = 2048 >> 8; // 2M buffer
544
        p[13] = 2048 & 0xff;
545
        p[14] = (16 * 176) >> 8; // 16x read speed current
546
        p[15] = (16 * 176) & 0xff;
547
        p[18] = (16 * 176) >> 8; // 16x write speed
548
        p[19] = (16 * 176) & 0xff;
549
        p[20] = (16 * 176) >> 8; // 16x write speed current
550
        p[21] = (16 * 176) & 0xff;
551
        return 22;
552

  
553
    default:
554
        return 0;
555
    }
556
}
557

  
558
static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
559
{
560
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
561
    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
562
    uint64_t nb_sectors;
563
    int page, dbd, buflen;
564
    uint8_t *p;
565

  
566
    dbd = req->cmd.buf[1]  & 0x8;
567
    page = req->cmd.buf[2] & 0x3f;
568
    DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer);
569
    memset(outbuf, 0, req->cmd.xfer);
570
    p = outbuf;
571

  
572
    p[1] = 0; /* Default media type.  */
573
    p[3] = 0; /* Block descriptor length.  */
574
    if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM ||
575
        bdrv_is_read_only(bdrv)) {
576
        p[2] = 0x80; /* Readonly.  */
577
    }
578
    p += 4;
579

  
580
    bdrv_get_geometry(bdrv, &nb_sectors);
581
    if ((~dbd) & nb_sectors) {
582
        outbuf[3] = 8; /* Block descriptor length  */
583
        nb_sectors /= s->cluster_size;
584
        nb_sectors--;
585
        if (nb_sectors > 0xffffff)
586
            nb_sectors = 0xffffff;
587
        p[0] = 0; /* media density code */
588
        p[1] = (nb_sectors >> 16) & 0xff;
589
        p[2] = (nb_sectors >> 8) & 0xff;
590
        p[3] = nb_sectors & 0xff;
591
        p[4] = 0; /* reserved */
592
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
593
        p[6] = s->cluster_size * 2;
594
        p[7] = 0;
595
        p += 8;
596
    }
597

  
598
    switch (page) {
599
    case 0x04:
600
    case 0x05:
601
    case 0x08:
602
    case 0x2a:
603
        p += mode_sense_page(req, page, p);
604
        break;
605
    case 0x3f:
606
        p += mode_sense_page(req, 0x08, p);
607
        p += mode_sense_page(req, 0x2a, p);
608
        break;
609
    }
610

  
611
    buflen = p - outbuf;
612
    outbuf[0] = buflen - 4;
613
    if (buflen > req->cmd.xfer)
614
        buflen = req->cmd.xfer;
615
    return buflen;
616
}
617

  
443 618
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
444 619
{
445 620
    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
......
473 648
        if (buflen < 0)
474 649
            goto illegal_request;
475 650
	break;
651
    case MODE_SENSE:
652
    case MODE_SENSE_10:
653
        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
654
        if (buflen < 0)
655
            goto illegal_request;
656
        break;
476 657
    case RESERVE:
477 658
        if (req->cmd.buf[1] & 1)
478 659
            goto illegal_request;
......
594 775
    case TEST_UNIT_READY:
595 776
    case REQUEST_SENSE:
596 777
    case INQUIRY:
778
    case MODE_SENSE:
779
    case MODE_SENSE_10:
597 780
    case RESERVE:
598 781
    case RESERVE_10:
599 782
    case RELEASE:
......
607 790
            return 0;
608 791
        }
609 792
        break;
610
    case MODE_SENSE:
611
    case MODE_SENSE_10:
612
        {
613
            uint8_t *p;
614
            int page;
615
            int dbd;
616
            
617
            dbd = buf[1]  & 0x8;
618
            page = buf[2] & 0x3f;
619
            DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
620
            p = outbuf;
621
            memset(p, 0, 4);
622
            outbuf[1] = 0; /* Default media type.  */
623
            outbuf[3] = 0; /* Block descriptor length.  */
624
            if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM ||
625
                bdrv_is_read_only(s->qdev.dinfo->bdrv)) {
626
                outbuf[2] = 0x80; /* Readonly.  */
627
            }
628
            p += 4;
629
            bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
630
            if ((~dbd) & nb_sectors) {
631
                nb_sectors /= s->cluster_size;
632
                nb_sectors--;
633
                if (nb_sectors > 0xffffff)
634
                    nb_sectors = 0xffffff;
635
                outbuf[3] = 8; /* Block descriptor length  */
636
                p[0] = 0; /* media density code */
637
                p[1] = (nb_sectors >> 16) & 0xff;
638
                p[2] = (nb_sectors >> 8) & 0xff;
639
                p[3] = nb_sectors & 0xff;
640
                p[4] = 0; /* reserved */
641
                p[5] = 0; /* bytes 5-7 are the sector size in bytes */
642
                p[6] = s->cluster_size * 2;
643
                p[7] = 0;
644
                p += 8;
645
            }
646

  
647
            if (page == 4) {
648
                int cylinders, heads, secs;
649

  
650
                /* Rigid disk device geometry page. */
651
                p[0] = 4;
652
                p[1] = 0x16;
653
                /* if a geometry hint is available, use it */
654
                bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
655
                p[2] = (cylinders >> 16) & 0xff;
656
                p[3] = (cylinders >> 8) & 0xff;
657
                p[4] = cylinders & 0xff;
658
                p[5] = heads & 0xff;
659
                /* Write precomp start cylinder, disabled */
660
                p[6] = (cylinders >> 16) & 0xff;
661
                p[7] = (cylinders >> 8) & 0xff;
662
                p[8] = cylinders & 0xff;
663
                /* Reduced current start cylinder, disabled */
664
                p[9] = (cylinders >> 16) & 0xff;
665
                p[10] = (cylinders >> 8) & 0xff;
666
                p[11] = cylinders & 0xff;
667
                /* Device step rate [ns], 200ns */
668
                p[12] = 0;
669
                p[13] = 200;
670
                /* Landing zone cylinder */
671
                p[14] = 0xff;
672
                p[15] =  0xff;
673
                p[16] = 0xff;
674
                /* Medium rotation rate [rpm], 5400 rpm */
675
                p[20] = (5400 >> 8) & 0xff;
676
                p[21] = 5400 & 0xff;
677
                p += 0x16;
678
            } else if (page == 5) {
679
                int cylinders, heads, secs;
680

  
681
                /* Flexible disk device geometry page. */
682
                p[0] = 5;
683
                p[1] = 0x1e;
684
                /* Transfer rate [kbit/s], 5Mbit/s */
685
                p[2] = 5000 >> 8;
686
                p[3] = 5000 & 0xff;
687
                /* if a geometry hint is available, use it */
688
                bdrv_get_geometry_hint(s->qdev.dinfo->bdrv, &cylinders, &heads, &secs);
689
                p[4] = heads & 0xff;
690
                p[5] = secs & 0xff;
691
                p[6] = s->cluster_size * 2;
692
                p[8] = (cylinders >> 8) & 0xff;
693
                p[9] = cylinders & 0xff;
694
                /* Write precomp start cylinder, disabled */
695
                p[10] = (cylinders >> 8) & 0xff;
696
                p[11] = cylinders & 0xff;
697
                /* Reduced current start cylinder, disabled */
698
                p[12] = (cylinders >> 8) & 0xff;
699
                p[13] = cylinders & 0xff;
700
                /* Device step rate [100us], 100us */
701
                p[14] = 0;
702
                p[15] = 1;
703
                /* Device step pulse width [us], 1us */
704
                p[16] = 1;
705
                /* Device head settle delay [100us], 100us */
706
                p[17] = 0;
707
                p[18] = 1;
708
                /* Motor on delay [0.1s], 0.1s */
709
                p[19] = 1;
710
                /* Motor off delay [0.1s], 0.1s */
711
                p[20] = 1;
712
                /* Medium rotation rate [rpm], 5400 rpm */
713
                p[28] = (5400 >> 8) & 0xff;
714
                p[29] = 5400 & 0xff;
715
                p += 0x1e;
716
            } else if ((page == 8 || page == 0x3f)) {
717
                /* Caching page.  */
718
                memset(p,0,20);
719
                p[0] = 8;
720
                p[1] = 0x12;
721
                if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
722
                     p[2] = 4; /* WCE */
723
                }
724
                p += 20;
725
            }
726
            if ((page == 0x3f || page == 0x2a)
727
                    && (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM)) {
728
                /* CD Capabilities and Mechanical Status page. */
729
                p[0] = 0x2a;
730
                p[1] = 0x14;
731
                p[2] = 3; // CD-R & CD-RW read
732
                p[3] = 0; // Writing not supported
733
                p[4] = 0x7f; /* Audio, composite, digital out,
734
                                         mode 2 form 1&2, multi session */
735
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
736
                                         RW corrected, C2 errors, ISRC,
737
                                         UPC, Bar code */
738
                p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
739
                /* Locking supported, jumper present, eject, tray */
740
                p[7] = 0; /* no volume & mute control, no
741
                                      changer */
742
                p[8] = (50 * 176) >> 8; // 50x read speed
743
                p[9] = (50 * 176) & 0xff;
744
                p[10] = 0 >> 8; // No volume
745
                p[11] = 0 & 0xff;
746
                p[12] = 2048 >> 8; // 2M buffer
747
                p[13] = 2048 & 0xff;
748
                p[14] = (16 * 176) >> 8; // 16x read speed current
749
                p[15] = (16 * 176) & 0xff;
750
                p[18] = (16 * 176) >> 8; // 16x write speed
751
                p[19] = (16 * 176) & 0xff;
752
                p[20] = (16 * 176) >> 8; // 16x write speed current
753
                p[21] = (16 * 176) & 0xff;
754
                p += 22;
755
            }
756
            r->iov.iov_len = p - outbuf;
757
            outbuf[0] = r->iov.iov_len - 4;
758
            if (r->iov.iov_len > len)
759
                r->iov.iov_len = len;
760
        }
761
        break;
762 793
    case START_STOP:
763 794
        DPRINTF("Start Stop Unit\n");
764 795
        if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM &&

Also available in: Unified diff