Commit 1a4f0c3a authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

scsi-disk: implement READ DISC INFORMATION



This command is not necessary for CD-ROM and DVD-ROM, but some versions of
udev trip on its absence.

Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 55042b95
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@
#define GET_EVENT_STATUS_NOTIFICATION 0x4a
#define LOG_SELECT            0x4c
#define LOG_SENSE             0x4d
#define READ_DISC_INFORMATION 0x51
#define RESERVE_TRACK         0x53
#define MODE_SELECT_10        0x55
#define RESERVE_10            0x56
+40 −0
Original line number Diff line number Diff line
@@ -724,6 +724,39 @@ static inline bool media_is_cd(SCSIDiskState *s)
    return nb_sectors <= CD_MAX_SECTORS;
}

static int scsi_read_disc_information(SCSIDiskState *s, SCSIDiskReq *r,
                                      uint8_t *outbuf)
{
    uint8_t type = r->req.cmd.buf[1] & 7;

    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }

    /* Types 1/2 are only defined for Blu-Ray.  */
    if (type != 0) {
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
        return -1;
    }

    memset(outbuf, 0, 34);
    outbuf[1] = 32;
    outbuf[2] = 0xe; /* last session complete, disc finalized */
    outbuf[3] = 1;   /* first track on disc */
    outbuf[4] = 1;   /* # of sessions */
    outbuf[5] = 1;   /* first track of last session */
    outbuf[6] = 1;   /* last track of last session */
    outbuf[7] = 0x20; /* unrestricted use */
    outbuf[8] = 0x00; /* CD-ROM or DVD-ROM */
    /* 9-10-11: most significant byte corresponding bytes 4-5-6 */
    /* 12-23: not meaningful for CD-ROM or DVD-ROM */
    /* 24-31: disc bar code */
    /* 32: disc application code */
    /* 33: number of OPC tables */

    return 34;
}

static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                   uint8_t *outbuf)
{
@@ -1363,6 +1396,12 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
            goto illegal_request;
        }
        break;
    case READ_DISC_INFORMATION:
        buflen = scsi_read_disc_information(s, r, outbuf);
        if (buflen < 0) {
            goto illegal_request;
        }
        break;
    case READ_DVD_STRUCTURE:
        buflen = scsi_read_dvd_structure(s, r, outbuf);
        if (buflen < 0) {
@@ -1490,6 +1529,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
    case ALLOW_MEDIUM_REMOVAL:
    case READ_CAPACITY_10:
    case READ_TOC:
    case READ_DISC_INFORMATION:
    case READ_DVD_STRUCTURE:
    case GET_CONFIGURATION:
    case GET_EVENT_STATUS_NOTIFICATION: