Merge remote-tracking branch 'kwolf/block-stable' into staging
This commit is contained in:
		
						commit
						54dcd0b37e
					
				@ -695,12 +695,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
    int action, code;
 | 
					    int action, code;
 | 
				
			||||||
    int max_len;
 | 
					    int max_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (buf[0] == GPCMD_MODE_SENSE_10) {
 | 
					 | 
				
			||||||
    max_len = ube16_to_cpu(buf + 7);
 | 
					    max_len = ube16_to_cpu(buf + 7);
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        max_len = buf[4];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    action = buf[2] >> 6;
 | 
					    action = buf[2] >> 6;
 | 
				
			||||||
    code = buf[2] & 0x3f;
 | 
					    code = buf[2] & 0x3f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -708,7 +703,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
    case 0: /* current values */
 | 
					    case 0: /* current values */
 | 
				
			||||||
        switch(code) {
 | 
					        switch(code) {
 | 
				
			||||||
        case MODE_PAGE_R_W_ERROR: /* error recovery */
 | 
					        case MODE_PAGE_R_W_ERROR: /* error recovery */
 | 
				
			||||||
            cpu_to_ube16(&buf[0], 16 + 6);
 | 
					            cpu_to_ube16(&buf[0], 16 - 2);
 | 
				
			||||||
            buf[2] = 0x70;
 | 
					            buf[2] = 0x70;
 | 
				
			||||||
            buf[3] = 0;
 | 
					            buf[3] = 0;
 | 
				
			||||||
            buf[4] = 0;
 | 
					            buf[4] = 0;
 | 
				
			||||||
@ -727,7 +722,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
            ide_atapi_cmd_reply(s, 16, max_len);
 | 
					            ide_atapi_cmd_reply(s, 16, max_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case MODE_PAGE_AUDIO_CTL:
 | 
					        case MODE_PAGE_AUDIO_CTL:
 | 
				
			||||||
            cpu_to_ube16(&buf[0], 24 + 6);
 | 
					            cpu_to_ube16(&buf[0], 24 - 2);
 | 
				
			||||||
            buf[2] = 0x70;
 | 
					            buf[2] = 0x70;
 | 
				
			||||||
            buf[3] = 0;
 | 
					            buf[3] = 0;
 | 
				
			||||||
            buf[4] = 0;
 | 
					            buf[4] = 0;
 | 
				
			||||||
@ -746,7 +741,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
            ide_atapi_cmd_reply(s, 24, max_len);
 | 
					            ide_atapi_cmd_reply(s, 24, max_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case MODE_PAGE_CAPABILITIES:
 | 
					        case MODE_PAGE_CAPABILITIES:
 | 
				
			||||||
            cpu_to_ube16(&buf[0], 28 + 6);
 | 
					            cpu_to_ube16(&buf[0], 30 - 2);
 | 
				
			||||||
            buf[2] = 0x70;
 | 
					            buf[2] = 0x70;
 | 
				
			||||||
            buf[3] = 0;
 | 
					            buf[3] = 0;
 | 
				
			||||||
            buf[4] = 0;
 | 
					            buf[4] = 0;
 | 
				
			||||||
@ -755,7 +750,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
            buf[7] = 0;
 | 
					            buf[7] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            buf[8] = MODE_PAGE_CAPABILITIES;
 | 
					            buf[8] = MODE_PAGE_CAPABILITIES;
 | 
				
			||||||
            buf[9] = 28 - 10;
 | 
					            buf[9] = 30 - 10;
 | 
				
			||||||
            buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
 | 
					            buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
 | 
				
			||||||
            buf[11] = 0x00;
 | 
					            buf[11] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -777,7 +772,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
 | 
				
			|||||||
            buf[25] = 0;
 | 
					            buf[25] = 0;
 | 
				
			||||||
            buf[26] = 0;
 | 
					            buf[26] = 0;
 | 
				
			||||||
            buf[27] = 0;
 | 
					            buf[27] = 0;
 | 
				
			||||||
            ide_atapi_cmd_reply(s, 28, max_len);
 | 
					            buf[28] = 0;
 | 
				
			||||||
 | 
					            buf[29] = 0;
 | 
				
			||||||
 | 
					            ide_atapi_cmd_reply(s, 30, max_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto error_cmd;
 | 
					            goto error_cmd;
 | 
				
			||||||
@ -1043,7 +1040,6 @@ static const struct {
 | 
				
			|||||||
    [ 0x00 ] = { cmd_test_unit_ready,               CHECK_READY },
 | 
					    [ 0x00 ] = { cmd_test_unit_ready,               CHECK_READY },
 | 
				
			||||||
    [ 0x03 ] = { cmd_request_sense,                 ALLOW_UA },
 | 
					    [ 0x03 ] = { cmd_request_sense,                 ALLOW_UA },
 | 
				
			||||||
    [ 0x12 ] = { cmd_inquiry,                       ALLOW_UA },
 | 
					    [ 0x12 ] = { cmd_inquiry,                       ALLOW_UA },
 | 
				
			||||||
    [ 0x1a ] = { cmd_mode_sense, /* (6) */          0 },
 | 
					 | 
				
			||||||
    [ 0x1b ] = { cmd_start_stop_unit,               0 }, /* [1] */
 | 
					    [ 0x1b ] = { cmd_start_stop_unit,               0 }, /* [1] */
 | 
				
			||||||
    [ 0x1e ] = { cmd_prevent_allow_medium_removal,  0 },
 | 
					    [ 0x1e ] = { cmd_prevent_allow_medium_removal,  0 },
 | 
				
			||||||
    [ 0x25 ] = { cmd_read_cdvd_capacity,            CHECK_READY },
 | 
					    [ 0x25 ] = { cmd_read_cdvd_capacity,            CHECK_READY },
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										128
									
								
								hw/scsi-bus.c
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								hw/scsi-bus.c
									
									
									
									
									
								
							@ -9,8 +9,6 @@
 | 
				
			|||||||
static char *scsibus_get_fw_dev_path(DeviceState *dev);
 | 
					static char *scsibus_get_fw_dev_path(DeviceState *dev);
 | 
				
			||||||
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 | 
					static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 | 
				
			||||||
static void scsi_req_dequeue(SCSIRequest *req);
 | 
					static void scsi_req_dequeue(SCSIRequest *req);
 | 
				
			||||||
static int scsi_build_sense(uint8_t *in_buf, int in_len,
 | 
					 | 
				
			||||||
                            uint8_t *buf, int len, bool fixed);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct BusInfo scsi_bus_info = {
 | 
					static struct BusInfo scsi_bus_info = {
 | 
				
			||||||
    .name  = "SCSI",
 | 
					    .name  = "SCSI",
 | 
				
			||||||
@ -502,7 +500,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
 | 
				
			|||||||
                                 hba_private);
 | 
					                                 hba_private);
 | 
				
			||||||
        } else if (lun != d->lun ||
 | 
					        } else if (lun != d->lun ||
 | 
				
			||||||
            buf[0] == REPORT_LUNS ||
 | 
					            buf[0] == REPORT_LUNS ||
 | 
				
			||||||
            buf[0] == REQUEST_SENSE) {
 | 
					            (buf[0] == REQUEST_SENSE && (d->sense_len || cmd.xfer < 4))) {
 | 
				
			||||||
            req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
 | 
					            req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
 | 
				
			||||||
                                 hba_private);
 | 
					                                 hba_private);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -649,6 +647,31 @@ static void scsi_req_dequeue(SCSIRequest *req)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int scsi_get_performance_length(int num_desc, int type, int data_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* MMC-6, paragraph 6.7.  */
 | 
				
			||||||
 | 
					    switch (type) {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
					        if ((data_type & 3) == 0) {
 | 
				
			||||||
 | 
					            /* Each descriptor is as in Table 295 - Nominal performance.  */
 | 
				
			||||||
 | 
					            return 16 * num_desc + 8;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Each descriptor is as in Table 296 - Exceptions.  */
 | 
				
			||||||
 | 
					            return 6 * num_desc + 8;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					    case 4:
 | 
				
			||||||
 | 
					    case 5:
 | 
				
			||||||
 | 
					        return 8 * num_desc + 8;
 | 
				
			||||||
 | 
					    case 2:
 | 
				
			||||||
 | 
					        return 2048 * num_desc + 8;
 | 
				
			||||||
 | 
					    case 3:
 | 
				
			||||||
 | 
					        return 16 * num_desc + 8;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        return 8;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
					static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (buf[0] >> 5) {
 | 
					    switch (buf[0] >> 5) {
 | 
				
			||||||
@ -666,11 +689,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
        cmd->len = 10;
 | 
					        cmd->len = 10;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 4:
 | 
					    case 4:
 | 
				
			||||||
        cmd->xfer = ldl_be_p(&buf[10]);
 | 
					        cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL;
 | 
				
			||||||
        cmd->len = 16;
 | 
					        cmd->len = 16;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 5:
 | 
					    case 5:
 | 
				
			||||||
        cmd->xfer = ldl_be_p(&buf[6]);
 | 
					        cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL;
 | 
				
			||||||
        cmd->len = 12;
 | 
					        cmd->len = 12;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
@ -681,8 +704,9 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
    case TEST_UNIT_READY:
 | 
					    case TEST_UNIT_READY:
 | 
				
			||||||
    case REWIND:
 | 
					    case REWIND:
 | 
				
			||||||
    case START_STOP:
 | 
					    case START_STOP:
 | 
				
			||||||
    case SEEK_6:
 | 
					    case SET_CAPACITY:
 | 
				
			||||||
    case WRITE_FILEMARKS:
 | 
					    case WRITE_FILEMARKS:
 | 
				
			||||||
 | 
					    case WRITE_FILEMARKS_16:
 | 
				
			||||||
    case SPACE:
 | 
					    case SPACE:
 | 
				
			||||||
    case RESERVE:
 | 
					    case RESERVE:
 | 
				
			||||||
    case RELEASE:
 | 
					    case RELEASE:
 | 
				
			||||||
@ -691,6 +715,8 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
    case VERIFY_10:
 | 
					    case VERIFY_10:
 | 
				
			||||||
    case SEEK_10:
 | 
					    case SEEK_10:
 | 
				
			||||||
    case SYNCHRONIZE_CACHE:
 | 
					    case SYNCHRONIZE_CACHE:
 | 
				
			||||||
 | 
					    case SYNCHRONIZE_CACHE_16:
 | 
				
			||||||
 | 
					    case LOCATE_16:
 | 
				
			||||||
    case LOCK_UNLOCK_CACHE:
 | 
					    case LOCK_UNLOCK_CACHE:
 | 
				
			||||||
    case LOAD_UNLOAD:
 | 
					    case LOAD_UNLOAD:
 | 
				
			||||||
    case SET_CD_SPEED:
 | 
					    case SET_CD_SPEED:
 | 
				
			||||||
@ -698,6 +724,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
    case WRITE_LONG_10:
 | 
					    case WRITE_LONG_10:
 | 
				
			||||||
    case MOVE_MEDIUM:
 | 
					    case MOVE_MEDIUM:
 | 
				
			||||||
    case UPDATE_BLOCK:
 | 
					    case UPDATE_BLOCK:
 | 
				
			||||||
 | 
					    case RESERVE_TRACK:
 | 
				
			||||||
 | 
					    case SET_READ_AHEAD:
 | 
				
			||||||
 | 
					    case PRE_FETCH:
 | 
				
			||||||
 | 
					    case PRE_FETCH_16:
 | 
				
			||||||
 | 
					    case ALLOW_OVERWRITE:
 | 
				
			||||||
        cmd->xfer = 0;
 | 
					        cmd->xfer = 0;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case MODE_SENSE:
 | 
					    case MODE_SENSE:
 | 
				
			||||||
@ -711,14 +742,13 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
    case READ_BLOCK_LIMITS:
 | 
					    case READ_BLOCK_LIMITS:
 | 
				
			||||||
        cmd->xfer = 6;
 | 
					        cmd->xfer = 6;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case READ_POSITION:
 | 
					 | 
				
			||||||
        cmd->xfer = 20;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case SEND_VOLUME_TAG:
 | 
					    case SEND_VOLUME_TAG:
 | 
				
			||||||
        cmd->xfer *= 40;
 | 
					        /* GPCMD_SET_STREAMING from multimedia commands.  */
 | 
				
			||||||
        break;
 | 
					        if (dev->type == TYPE_ROM) {
 | 
				
			||||||
    case MEDIUM_SCAN:
 | 
					            cmd->xfer = buf[10] | (buf[9] << 8);
 | 
				
			||||||
        cmd->xfer *= 8;
 | 
					        } else {
 | 
				
			||||||
 | 
					            cmd->xfer = buf[9] | (buf[8] << 8);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case WRITE_10:
 | 
					    case WRITE_10:
 | 
				
			||||||
    case WRITE_VERIFY_10:
 | 
					    case WRITE_VERIFY_10:
 | 
				
			||||||
@ -737,9 +767,39 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 | 
				
			|||||||
    case READ_16:
 | 
					    case READ_16:
 | 
				
			||||||
        cmd->xfer *= dev->blocksize;
 | 
					        cmd->xfer *= dev->blocksize;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case FORMAT_UNIT:
 | 
				
			||||||
 | 
					        /* MMC mandates the parameter list to be 12-bytes long.  Parameters
 | 
				
			||||||
 | 
					         * for block devices are restricted to the header right now.  */
 | 
				
			||||||
 | 
					        if (dev->type == TYPE_ROM && (buf[1] & 16)) {
 | 
				
			||||||
 | 
					            cmd->xfer = 12;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            cmd->xfer = (buf[1] & 16) == 0 ? 0 : (buf[1] & 32 ? 8 : 4);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case INQUIRY:
 | 
					    case INQUIRY:
 | 
				
			||||||
 | 
					    case RECEIVE_DIAGNOSTIC:
 | 
				
			||||||
 | 
					    case SEND_DIAGNOSTIC:
 | 
				
			||||||
        cmd->xfer = buf[4] | (buf[3] << 8);
 | 
					        cmd->xfer = buf[4] | (buf[3] << 8);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case READ_CD:
 | 
				
			||||||
 | 
					    case READ_BUFFER:
 | 
				
			||||||
 | 
					    case WRITE_BUFFER:
 | 
				
			||||||
 | 
					    case SEND_CUE_SHEET:
 | 
				
			||||||
 | 
					        cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PERSISTENT_RESERVE_OUT:
 | 
				
			||||||
 | 
					        cmd->xfer = ldl_be_p(&buf[5]) & 0xffffffffULL;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case ERASE_12:
 | 
				
			||||||
 | 
					        if (dev->type == TYPE_ROM) {
 | 
				
			||||||
 | 
					            /* MMC command GET PERFORMANCE.  */
 | 
				
			||||||
 | 
					            cmd->xfer = scsi_get_performance_length(buf[9] | (buf[8] << 8),
 | 
				
			||||||
 | 
					                                                    buf[10], buf[1] & 0x1f);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case MECHANISM_STATUS:
 | 
				
			||||||
 | 
					    case READ_DVD_STRUCTURE:
 | 
				
			||||||
 | 
					    case SEND_DVD_STRUCTURE:
 | 
				
			||||||
    case MAINTENANCE_OUT:
 | 
					    case MAINTENANCE_OUT:
 | 
				
			||||||
    case MAINTENANCE_IN:
 | 
					    case MAINTENANCE_IN:
 | 
				
			||||||
        if (dev->type == TYPE_ROM) {
 | 
					        if (dev->type == TYPE_ROM) {
 | 
				
			||||||
@ -755,6 +815,10 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    switch (buf[0]) {
 | 
					    switch (buf[0]) {
 | 
				
			||||||
    /* stream commands */
 | 
					    /* stream commands */
 | 
				
			||||||
 | 
					    case ERASE_12:
 | 
				
			||||||
 | 
					    case ERASE_16:
 | 
				
			||||||
 | 
					        cmd->xfer = 0;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case READ_6:
 | 
					    case READ_6:
 | 
				
			||||||
    case READ_REVERSE:
 | 
					    case READ_REVERSE:
 | 
				
			||||||
    case RECOVER_BUFFERED_DATA:
 | 
					    case RECOVER_BUFFERED_DATA:
 | 
				
			||||||
@ -770,6 +834,15 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
 | 
				
			|||||||
        cmd->len = 6;
 | 
					        cmd->len = 6;
 | 
				
			||||||
        cmd->xfer = 0;
 | 
					        cmd->xfer = 0;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case SPACE_16:
 | 
				
			||||||
 | 
					        cmd->xfer = buf[13] | (buf[12] << 8);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case READ_POSITION:
 | 
				
			||||||
 | 
					        cmd->xfer = buf[8] | (buf[7] << 8);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case FORMAT_UNIT:
 | 
				
			||||||
 | 
					        cmd->xfer = buf[4] | (buf[3] << 8);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    /* generic commands */
 | 
					    /* generic commands */
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        return scsi_req_length(cmd, dev, buf);
 | 
					        return scsi_req_length(cmd, dev, buf);
 | 
				
			||||||
@ -809,6 +882,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
 | 
				
			|||||||
    case SEARCH_LOW_12:
 | 
					    case SEARCH_LOW_12:
 | 
				
			||||||
    case MEDIUM_SCAN:
 | 
					    case MEDIUM_SCAN:
 | 
				
			||||||
    case SEND_VOLUME_TAG:
 | 
					    case SEND_VOLUME_TAG:
 | 
				
			||||||
 | 
					    case SEND_CUE_SHEET:
 | 
				
			||||||
 | 
					    case SEND_DVD_STRUCTURE:
 | 
				
			||||||
    case PERSISTENT_RESERVE_OUT:
 | 
					    case PERSISTENT_RESERVE_OUT:
 | 
				
			||||||
    case MAINTENANCE_OUT:
 | 
					    case MAINTENANCE_OUT:
 | 
				
			||||||
        cmd->mode = SCSI_XFER_TO_DEV;
 | 
					        cmd->mode = SCSI_XFER_TO_DEV;
 | 
				
			||||||
@ -835,7 +910,7 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
 | 
				
			|||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 5:
 | 
					    case 5:
 | 
				
			||||||
        lba = ldl_be_p(&buf[2]);
 | 
					        lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 4:
 | 
					    case 4:
 | 
				
			||||||
        lba = ldq_be_p(&buf[2]);
 | 
					        lba = ldq_be_p(&buf[2]);
 | 
				
			||||||
@ -1036,7 +1111,7 @@ static const char *scsi_command_name(uint8_t cmd)
 | 
				
			|||||||
        [ REASSIGN_BLOCKS          ] = "REASSIGN_BLOCKS",
 | 
					        [ REASSIGN_BLOCKS          ] = "REASSIGN_BLOCKS",
 | 
				
			||||||
        [ READ_6                   ] = "READ_6",
 | 
					        [ READ_6                   ] = "READ_6",
 | 
				
			||||||
        [ WRITE_6                  ] = "WRITE_6",
 | 
					        [ WRITE_6                  ] = "WRITE_6",
 | 
				
			||||||
        [ SEEK_6                   ] = "SEEK_6",
 | 
					        [ SET_CAPACITY             ] = "SET_CAPACITY",
 | 
				
			||||||
        [ READ_REVERSE             ] = "READ_REVERSE",
 | 
					        [ READ_REVERSE             ] = "READ_REVERSE",
 | 
				
			||||||
        [ WRITE_FILEMARKS          ] = "WRITE_FILEMARKS",
 | 
					        [ WRITE_FILEMARKS          ] = "WRITE_FILEMARKS",
 | 
				
			||||||
        [ SPACE                    ] = "SPACE",
 | 
					        [ SPACE                    ] = "SPACE",
 | 
				
			||||||
@ -1064,7 +1139,7 @@ static const char *scsi_command_name(uint8_t cmd)
 | 
				
			|||||||
        [ SEARCH_EQUAL             ] = "SEARCH_EQUAL",
 | 
					        [ SEARCH_EQUAL             ] = "SEARCH_EQUAL",
 | 
				
			||||||
        [ SEARCH_LOW               ] = "SEARCH_LOW",
 | 
					        [ SEARCH_LOW               ] = "SEARCH_LOW",
 | 
				
			||||||
        [ SET_LIMITS               ] = "SET_LIMITS",
 | 
					        [ SET_LIMITS               ] = "SET_LIMITS",
 | 
				
			||||||
        [ PRE_FETCH                ] = "PRE_FETCH",
 | 
					        [ PRE_FETCH                ] = "PRE_FETCH/READ_POSITION",
 | 
				
			||||||
        /* READ_POSITION and PRE_FETCH use the same operation code */
 | 
					        /* READ_POSITION and PRE_FETCH use the same operation code */
 | 
				
			||||||
        [ SYNCHRONIZE_CACHE        ] = "SYNCHRONIZE_CACHE",
 | 
					        [ SYNCHRONIZE_CACHE        ] = "SYNCHRONIZE_CACHE",
 | 
				
			||||||
        [ LOCK_UNLOCK_CACHE        ] = "LOCK_UNLOCK_CACHE",
 | 
					        [ LOCK_UNLOCK_CACHE        ] = "LOCK_UNLOCK_CACHE",
 | 
				
			||||||
@ -1101,9 +1176,11 @@ static const char *scsi_command_name(uint8_t cmd)
 | 
				
			|||||||
        [ WRITE_16                 ] = "WRITE_16",
 | 
					        [ WRITE_16                 ] = "WRITE_16",
 | 
				
			||||||
        [ WRITE_VERIFY_16          ] = "WRITE_VERIFY_16",
 | 
					        [ WRITE_VERIFY_16          ] = "WRITE_VERIFY_16",
 | 
				
			||||||
        [ VERIFY_16                ] = "VERIFY_16",
 | 
					        [ VERIFY_16                ] = "VERIFY_16",
 | 
				
			||||||
        [ SYNCHRONIZE_CACHE_16     ] = "SYNCHRONIZE_CACHE_16",
 | 
					        [ PRE_FETCH_16             ] = "PRE_FETCH_16",
 | 
				
			||||||
 | 
					        [ SYNCHRONIZE_CACHE_16     ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
 | 
				
			||||||
 | 
					        /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
 | 
				
			||||||
        [ LOCATE_16                ] = "LOCATE_16",
 | 
					        [ LOCATE_16                ] = "LOCATE_16",
 | 
				
			||||||
        [ WRITE_SAME_16            ] = "WRITE_SAME_16",
 | 
					        [ WRITE_SAME_16            ] = "ERASE_16/WRITE_SAME_16",
 | 
				
			||||||
        /* ERASE_16 and WRITE_SAME_16 use the same operation code */
 | 
					        /* ERASE_16 and WRITE_SAME_16 use the same operation code */
 | 
				
			||||||
        [ SERVICE_ACTION_IN_16     ] = "SERVICE_ACTION_IN_16",
 | 
					        [ SERVICE_ACTION_IN_16     ] = "SERVICE_ACTION_IN_16",
 | 
				
			||||||
        [ WRITE_LONG_16            ] = "WRITE_LONG_16",
 | 
					        [ WRITE_LONG_16            ] = "WRITE_LONG_16",
 | 
				
			||||||
@ -1113,6 +1190,8 @@ static const char *scsi_command_name(uint8_t cmd)
 | 
				
			|||||||
        [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
 | 
					        [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
 | 
				
			||||||
        [ READ_12                  ] = "READ_12",
 | 
					        [ READ_12                  ] = "READ_12",
 | 
				
			||||||
        [ WRITE_12                 ] = "WRITE_12",
 | 
					        [ WRITE_12                 ] = "WRITE_12",
 | 
				
			||||||
 | 
					        [ ERASE_12                 ] = "ERASE_12/GET_PERFORMANCE",
 | 
				
			||||||
 | 
					        /* ERASE_12 and GET_PERFORMANCE use the same operation code */
 | 
				
			||||||
        [ SERVICE_ACTION_IN_12     ] = "SERVICE_ACTION_IN_12",
 | 
					        [ SERVICE_ACTION_IN_12     ] = "SERVICE_ACTION_IN_12",
 | 
				
			||||||
        [ WRITE_VERIFY_12          ] = "WRITE_VERIFY_12",
 | 
					        [ WRITE_VERIFY_12          ] = "WRITE_VERIFY_12",
 | 
				
			||||||
        [ VERIFY_12                ] = "VERIFY_12",
 | 
					        [ VERIFY_12                ] = "VERIFY_12",
 | 
				
			||||||
@ -1120,9 +1199,18 @@ static const char *scsi_command_name(uint8_t cmd)
 | 
				
			|||||||
        [ SEARCH_EQUAL_12          ] = "SEARCH_EQUAL_12",
 | 
					        [ SEARCH_EQUAL_12          ] = "SEARCH_EQUAL_12",
 | 
				
			||||||
        [ SEARCH_LOW_12            ] = "SEARCH_LOW_12",
 | 
					        [ SEARCH_LOW_12            ] = "SEARCH_LOW_12",
 | 
				
			||||||
        [ READ_ELEMENT_STATUS      ] = "READ_ELEMENT_STATUS",
 | 
					        [ READ_ELEMENT_STATUS      ] = "READ_ELEMENT_STATUS",
 | 
				
			||||||
        [ SEND_VOLUME_TAG          ] = "SEND_VOLUME_TAG",
 | 
					        [ SEND_VOLUME_TAG          ] = "SEND_VOLUME_TAG/SET_STREAMING",
 | 
				
			||||||
 | 
					        /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
 | 
				
			||||||
 | 
					        [ READ_CD                  ] = "READ_CD",
 | 
				
			||||||
        [ READ_DEFECT_DATA_12      ] = "READ_DEFECT_DATA_12",
 | 
					        [ READ_DEFECT_DATA_12      ] = "READ_DEFECT_DATA_12",
 | 
				
			||||||
 | 
					        [ READ_DVD_STRUCTURE       ] = "READ_DVD_STRUCTURE",
 | 
				
			||||||
 | 
					        [ RESERVE_TRACK            ] = "RESERVE_TRACK",
 | 
				
			||||||
 | 
					        [ SEND_CUE_SHEET           ] = "SEND_CUE_SHEET",
 | 
				
			||||||
 | 
					        [ SEND_DVD_STRUCTURE       ] = "SEND_DVD_STRUCTURE",
 | 
				
			||||||
        [ SET_CD_SPEED             ] = "SET_CD_SPEED",
 | 
					        [ SET_CD_SPEED             ] = "SET_CD_SPEED",
 | 
				
			||||||
 | 
					        [ SET_READ_AHEAD           ] = "SET_READ_AHEAD",
 | 
				
			||||||
 | 
					        [ ALLOW_OVERWRITE          ] = "ALLOW_OVERWRITE",
 | 
				
			||||||
 | 
					        [ MECHANISM_STATUS         ] = "MECHANISM_STATUS",
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
 | 
					    if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
 | 
				
			||||||
@ -1279,7 +1367,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
 | 
				
			|||||||
    SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
 | 
					    SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
 | 
				
			||||||
    char path[100];
 | 
					    char path[100];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
 | 
					    snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev),
 | 
				
			||||||
             d->channel, d->id, d->lun);
 | 
					             d->channel, d->id, d->lun);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return strdup(path);
 | 
					    return strdup(path);
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@
 | 
				
			|||||||
#define REASSIGN_BLOCKS       0x07
 | 
					#define REASSIGN_BLOCKS       0x07
 | 
				
			||||||
#define READ_6                0x08
 | 
					#define READ_6                0x08
 | 
				
			||||||
#define WRITE_6               0x0a
 | 
					#define WRITE_6               0x0a
 | 
				
			||||||
#define SEEK_6                0x0b
 | 
					#define SET_CAPACITY          0x0b
 | 
				
			||||||
#define READ_REVERSE          0x0f
 | 
					#define READ_REVERSE          0x0f
 | 
				
			||||||
#define WRITE_FILEMARKS       0x10
 | 
					#define WRITE_FILEMARKS       0x10
 | 
				
			||||||
#define SPACE                 0x11
 | 
					#define SPACE                 0x11
 | 
				
			||||||
@ -81,14 +81,17 @@
 | 
				
			|||||||
#define GET_EVENT_STATUS_NOTIFICATION 0x4a
 | 
					#define GET_EVENT_STATUS_NOTIFICATION 0x4a
 | 
				
			||||||
#define LOG_SELECT            0x4c
 | 
					#define LOG_SELECT            0x4c
 | 
				
			||||||
#define LOG_SENSE             0x4d
 | 
					#define LOG_SENSE             0x4d
 | 
				
			||||||
 | 
					#define RESERVE_TRACK         0x53
 | 
				
			||||||
#define MODE_SELECT_10        0x55
 | 
					#define MODE_SELECT_10        0x55
 | 
				
			||||||
#define RESERVE_10            0x56
 | 
					#define RESERVE_10            0x56
 | 
				
			||||||
#define RELEASE_10            0x57
 | 
					#define RELEASE_10            0x57
 | 
				
			||||||
#define MODE_SENSE_10         0x5a
 | 
					#define MODE_SENSE_10         0x5a
 | 
				
			||||||
 | 
					#define SEND_CUE_SHEET        0x5d
 | 
				
			||||||
#define PERSISTENT_RESERVE_IN 0x5e
 | 
					#define PERSISTENT_RESERVE_IN 0x5e
 | 
				
			||||||
#define PERSISTENT_RESERVE_OUT 0x5f
 | 
					#define PERSISTENT_RESERVE_OUT 0x5f
 | 
				
			||||||
#define VARLENGTH_CDB         0x7f
 | 
					#define VARLENGTH_CDB         0x7f
 | 
				
			||||||
#define WRITE_FILEMARKS_16    0x80
 | 
					#define WRITE_FILEMARKS_16    0x80
 | 
				
			||||||
 | 
					#define ALLOW_OVERWRITE       0x82
 | 
				
			||||||
#define EXTENDED_COPY         0x83
 | 
					#define EXTENDED_COPY         0x83
 | 
				
			||||||
#define ATA_PASSTHROUGH       0x85
 | 
					#define ATA_PASSTHROUGH       0x85
 | 
				
			||||||
#define ACCESS_CONTROL_IN     0x86
 | 
					#define ACCESS_CONTROL_IN     0x86
 | 
				
			||||||
@ -98,6 +101,8 @@
 | 
				
			|||||||
#define WRITE_16              0x8a
 | 
					#define WRITE_16              0x8a
 | 
				
			||||||
#define WRITE_VERIFY_16       0x8e
 | 
					#define WRITE_VERIFY_16       0x8e
 | 
				
			||||||
#define VERIFY_16             0x8f
 | 
					#define VERIFY_16             0x8f
 | 
				
			||||||
 | 
					#define PRE_FETCH_16          0x90
 | 
				
			||||||
 | 
					#define SPACE_16              0x91
 | 
				
			||||||
#define SYNCHRONIZE_CACHE_16  0x91
 | 
					#define SYNCHRONIZE_CACHE_16  0x91
 | 
				
			||||||
#define LOCATE_16             0x92
 | 
					#define LOCATE_16             0x92
 | 
				
			||||||
#define WRITE_SAME_16         0x93
 | 
					#define WRITE_SAME_16         0x93
 | 
				
			||||||
@ -110,9 +115,11 @@
 | 
				
			|||||||
#define MAINTENANCE_OUT       0xa4
 | 
					#define MAINTENANCE_OUT       0xa4
 | 
				
			||||||
#define MOVE_MEDIUM           0xa5
 | 
					#define MOVE_MEDIUM           0xa5
 | 
				
			||||||
#define LOAD_UNLOAD           0xa6
 | 
					#define LOAD_UNLOAD           0xa6
 | 
				
			||||||
 | 
					#define SET_READ_AHEAD        0xa7
 | 
				
			||||||
#define READ_12               0xa8
 | 
					#define READ_12               0xa8
 | 
				
			||||||
#define WRITE_12              0xaa
 | 
					#define WRITE_12              0xaa
 | 
				
			||||||
#define SERVICE_ACTION_IN_12  0xab
 | 
					#define SERVICE_ACTION_IN_12  0xab
 | 
				
			||||||
 | 
					#define ERASE_12              0xac
 | 
				
			||||||
#define READ_DVD_STRUCTURE    0xad
 | 
					#define READ_DVD_STRUCTURE    0xad
 | 
				
			||||||
#define WRITE_VERIFY_12       0xae
 | 
					#define WRITE_VERIFY_12       0xae
 | 
				
			||||||
#define VERIFY_12             0xaf
 | 
					#define VERIFY_12             0xaf
 | 
				
			||||||
@ -125,6 +132,7 @@
 | 
				
			|||||||
#define SET_CD_SPEED          0xbb
 | 
					#define SET_CD_SPEED          0xbb
 | 
				
			||||||
#define MECHANISM_STATUS      0xbd
 | 
					#define MECHANISM_STATUS      0xbd
 | 
				
			||||||
#define READ_CD               0xbe
 | 
					#define READ_CD               0xbe
 | 
				
			||||||
 | 
					#define SEND_DVD_STRUCTURE    0xbf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * SERVICE ACTION IN subcodes
 | 
					 * SERVICE ACTION IN subcodes
 | 
				
			||||||
 | 
				
			|||||||
@ -797,7 +797,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /* if a geometry hint is available, use it */
 | 
					        /* if a geometry hint is available, use it */
 | 
				
			||||||
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
 | 
					        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
 | 
				
			||||||
        p[2] = (cylinders >> 16) & 0xff;
 | 
					        p[2] = (cylinders >> 16) & 0xff;
 | 
				
			||||||
        p[3] = (cylinders >> 8) & 0xff;
 | 
					        p[3] = (cylinders >> 8) & 0xff;
 | 
				
			||||||
        p[4] = cylinders & 0xff;
 | 
					        p[4] = cylinders & 0xff;
 | 
				
			||||||
@ -831,7 +831,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
 | 
				
			|||||||
        p[2] = 5000 >> 8;
 | 
					        p[2] = 5000 >> 8;
 | 
				
			||||||
        p[3] = 5000 & 0xff;
 | 
					        p[3] = 5000 & 0xff;
 | 
				
			||||||
        /* if a geometry hint is available, use it */
 | 
					        /* if a geometry hint is available, use it */
 | 
				
			||||||
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
 | 
					        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
 | 
				
			||||||
        p[4] = heads & 0xff;
 | 
					        p[4] = heads & 0xff;
 | 
				
			||||||
        p[5] = secs & 0xff;
 | 
					        p[5] = secs & 0xff;
 | 
				
			||||||
        p[6] = s->qdev.blocksize >> 8;
 | 
					        p[6] = s->qdev.blocksize >> 8;
 | 
				
			||||||
@ -956,8 +956,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
 | 
				
			|||||||
        p += 8;
 | 
					        p += 8;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* MMC prescribes that CD/DVD drives have no block descriptors.  */
 | 
				
			||||||
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
 | 
					    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
 | 
				
			||||||
    if (!dbd && nb_sectors) {
 | 
					    if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
 | 
				
			||||||
        if (r->req.cmd.buf[0] == MODE_SENSE) {
 | 
					        if (r->req.cmd.buf[0] == MODE_SENSE) {
 | 
				
			||||||
            outbuf[3] = 8; /* Block descriptor length  */
 | 
					            outbuf[3] = 8; /* Block descriptor length  */
 | 
				
			||||||
        } else { /* MODE_SENSE_10 */
 | 
					        } else { /* MODE_SENSE_10 */
 | 
				
			||||||
@ -1178,6 +1179,11 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
 | 
				
			|||||||
        outbuf[7] = 0;
 | 
					        outbuf[7] = 0;
 | 
				
			||||||
        buflen = 8;
 | 
					        buflen = 8;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case REQUEST_SENSE:
 | 
				
			||||||
 | 
					        /* Just return "NO SENSE".  */
 | 
				
			||||||
 | 
					        buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
 | 
				
			||||||
 | 
					                                  (req->cmd.buf[1] & 1) == 0);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case MECHANISM_STATUS:
 | 
					    case MECHANISM_STATUS:
 | 
				
			||||||
        buflen = scsi_emulate_mechanism_status(s, outbuf);
 | 
					        buflen = scsi_emulate_mechanism_status(s, outbuf);
 | 
				
			||||||
        if (buflen < 0) {
 | 
					        if (buflen < 0) {
 | 
				
			||||||
@ -1312,6 +1318,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 | 
				
			|||||||
    case GET_EVENT_STATUS_NOTIFICATION:
 | 
					    case GET_EVENT_STATUS_NOTIFICATION:
 | 
				
			||||||
    case MECHANISM_STATUS:
 | 
					    case MECHANISM_STATUS:
 | 
				
			||||||
    case SERVICE_ACTION_IN_16:
 | 
					    case SERVICE_ACTION_IN_16:
 | 
				
			||||||
 | 
					    case REQUEST_SENSE:
 | 
				
			||||||
    case VERIFY_10:
 | 
					    case VERIFY_10:
 | 
				
			||||||
        rc = scsi_disk_emulate_command(r);
 | 
					        rc = scsi_disk_emulate_command(r);
 | 
				
			||||||
        if (rc < 0) {
 | 
					        if (rc < 0) {
 | 
				
			||||||
@ -1374,10 +1381,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 | 
				
			|||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case SEEK_6:
 | 
					 | 
				
			||||||
    case SEEK_10:
 | 
					    case SEEK_10:
 | 
				
			||||||
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
 | 
					        DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
 | 
				
			||||||
                r->req.cmd.lba);
 | 
					 | 
				
			||||||
        if (r->req.cmd.lba > s->qdev.max_lba) {
 | 
					        if (r->req.cmd.lba > s->qdev.max_lba) {
 | 
				
			||||||
            goto illegal_lba;
 | 
					            goto illegal_lba;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1408,8 +1413,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case REQUEST_SENSE:
 | 
					 | 
				
			||||||
        abort();
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
 | 
					        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
 | 
				
			||||||
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
 | 
					        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
 | 
				
			||||||
@ -1553,7 +1556,7 @@ static int scsi_initfn(SCSIDevice *dev)
 | 
				
			|||||||
    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 | 
					    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdrv_iostatus_enable(s->qdev.conf.bs);
 | 
					    bdrv_iostatus_enable(s->qdev.conf.bs);
 | 
				
			||||||
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
 | 
					    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1700,9 +1703,21 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
 | 
				
			|||||||
    case WRITE_VERIFY_10:
 | 
					    case WRITE_VERIFY_10:
 | 
				
			||||||
    case WRITE_VERIFY_12:
 | 
					    case WRITE_VERIFY_12:
 | 
				
			||||||
    case WRITE_VERIFY_16:
 | 
					    case WRITE_VERIFY_16:
 | 
				
			||||||
 | 
					        /* MMC writing cannot be done via pread/pwrite, because it sometimes
 | 
				
			||||||
 | 
					         * involves writing beyond the maximum LBA or to negative LBA (lead-in).
 | 
				
			||||||
 | 
					         * And once you do these writes, reading from the block device is
 | 
				
			||||||
 | 
					         * unreliable, too.  It is even possible that reads deliver random data
 | 
				
			||||||
 | 
					         * from the host page cache (this is probably a Linux bug).
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * We might use scsi_disk_reqops as long as no writing commands are
 | 
				
			||||||
 | 
					         * seen, but performance usually isn't paramount on optical media.  So,
 | 
				
			||||||
 | 
					         * just make scsi-block operate the same as scsi-generic for them.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if (s->qdev.type != TYPE_ROM) {
 | 
				
			||||||
            return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
 | 
					            return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
 | 
				
			||||||
                                  hba_private);
 | 
					                                  hba_private);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
 | 
					    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
 | 
				
			||||||
                          hba_private);
 | 
					                          hba_private);
 | 
				
			||||||
 | 
				
			|||||||
@ -179,6 +179,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
 | 
				
			|||||||
#define SENSE_CODE(x) sense_code_ ## x
 | 
					#define SENSE_CODE(x) sense_code_ ## x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int scsi_sense_valid(SCSISense sense);
 | 
					int scsi_sense_valid(SCSISense sense);
 | 
				
			||||||
 | 
					int scsi_build_sense(uint8_t *in_buf, int in_len,
 | 
				
			||||||
 | 
					                     uint8_t *buf, int len, bool fixed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
 | 
					SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
 | 
				
			||||||
                            uint32_t tag, uint32_t lun, void *hba_private);
 | 
					                            uint32_t tag, uint32_t lun, void *hba_private);
 | 
				
			||||||
 | 
				
			|||||||
@ -421,6 +421,7 @@ snapshots.
 | 
				
			|||||||
* disk_images_fat_images::    Virtual FAT disk images
 | 
					* disk_images_fat_images::    Virtual FAT disk images
 | 
				
			||||||
* disk_images_nbd::           NBD access
 | 
					* disk_images_nbd::           NBD access
 | 
				
			||||||
* disk_images_sheepdog::      Sheepdog disk images
 | 
					* disk_images_sheepdog::      Sheepdog disk images
 | 
				
			||||||
 | 
					* disk_images_iscsi::         iSCSI LUNs
 | 
				
			||||||
@end menu
 | 
					@end menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@node disk_images_quickstart
 | 
					@node disk_images_quickstart
 | 
				
			||||||
@ -695,6 +696,61 @@ qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
 | 
				
			|||||||
qemu sheepdog:@var{hostname}:@var{port}:@var{image}
 | 
					qemu sheepdog:@var{hostname}:@var{port}:@var{image}
 | 
				
			||||||
@end example
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@node disk_images_iscsi
 | 
				
			||||||
 | 
					@subsection iSCSI LUNs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					iSCSI is a popular protocol used to access SCSI devices across a computer
 | 
				
			||||||
 | 
					network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are two different ways iSCSI devices can be used by QEMU.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The first method is to mount the iSCSI LUN on the host, and make it appear as
 | 
				
			||||||
 | 
					any other ordinary SCSI device on the host and then to access this device as a
 | 
				
			||||||
 | 
					/dev/sd device from QEMU. How to do this differs between host OSes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The second method involves using the iSCSI initiator that is built into
 | 
				
			||||||
 | 
					QEMU. This provides a mechanism that works the same way regardless of which
 | 
				
			||||||
 | 
					host OS you are running QEMU on. This section will describe this second method
 | 
				
			||||||
 | 
					of using iSCSI together with QEMU.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In QEMU, iSCSI devices are described using special iSCSI URLs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					URL syntax:
 | 
				
			||||||
 | 
					iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Username and password are optional and only used if your target is set up
 | 
				
			||||||
 | 
					using CHAP authentication for access control.
 | 
				
			||||||
 | 
					Alternatively the username and password can also be set via environment
 | 
				
			||||||
 | 
					variables to have these not show up in the process list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					export LIBISCSI_CHAP_USERNAME=<username>
 | 
				
			||||||
 | 
					export LIBISCSI_CHAP_PASSWORD=<password>
 | 
				
			||||||
 | 
					iscsi://<host>/<target-iqn-name>/<lun>
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					This example shows how to set up an iSCSI target with one CDROM and one DISK
 | 
				
			||||||
 | 
					using the Linux STGT software target. This target is available on Red Hat based
 | 
				
			||||||
 | 
					systems as the package 'scsi-target-utils'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tgtd --iscsi portal=127.0.0.1:3260
 | 
				
			||||||
 | 
					tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test
 | 
				
			||||||
 | 
					tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \
 | 
				
			||||||
 | 
					    -b /IMAGES/disk.img --device-type=disk
 | 
				
			||||||
 | 
					tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
 | 
				
			||||||
 | 
					    -b /IMAGES/cd.iso --device-type=cd
 | 
				
			||||||
 | 
					tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qemu-system-i386 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
 | 
				
			||||||
 | 
					    -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@node pcsys_network
 | 
					@node pcsys_network
 | 
				
			||||||
@section Network emulation
 | 
					@section Network emulation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user