diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
| -rw-r--r-- | drivers/scsi/scsi_debug.c | 361 | 
1 files changed, 206 insertions, 155 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index f0eec4708ddd..aef33d1e346a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -162,7 +162,7 @@ static const char *sdebug_version_date = "20210520";  #define DEF_VPD_USE_HOSTNO 1  #define DEF_WRITESAME_LENGTH 0xFFFF  #define DEF_ATOMIC_WR 0 -#define DEF_ATOMIC_WR_MAX_LENGTH 8192 +#define DEF_ATOMIC_WR_MAX_LENGTH 128  #define DEF_ATOMIC_WR_ALIGN 2  #define DEF_ATOMIC_WR_GRAN 2  #define DEF_ATOMIC_WR_MAX_LENGTH_BNDRY (DEF_ATOMIC_WR_MAX_LENGTH) @@ -294,6 +294,14 @@ struct tape_block {  #define FF_SA (F_SA_HIGH | F_SA_LOW)  #define F_LONG_DELAY		(F_SSU_DELAY | F_SYNC_DELAY) +/* Device selection bit mask */ +#define DS_ALL     0xffffffff +#define DS_SBC     (1 << TYPE_DISK) +#define DS_SSC     (1 << TYPE_TAPE) +#define DS_ZBC     (1 << TYPE_ZBC) + +#define DS_NO_SSC  (DS_ALL & ~DS_SSC) +  #define SDEBUG_MAX_PARTS 4  #define SDEBUG_MAX_CMD_LEN 32 @@ -472,6 +480,7 @@ struct opcode_info_t {  				/* for terminating element */  	u8 opcode;		/* if num_attached > 0, preferred */  	u16 sa;			/* service action */ +	u32 devsel;		/* device type mask for this definition */  	u32 flags;		/* OR-ed set of SDEB_F_* */  	int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);  	const struct opcode_info_t *arrp;  /* num_attached elements or NULL */ @@ -519,7 +528,8 @@ enum sdeb_opcode_index {  	SDEB_I_WRITE_FILEMARKS = 35,  	SDEB_I_SPACE = 36,  	SDEB_I_FORMAT_MEDIUM = 37, -	SDEB_I_LAST_ELEM_P1 = 38,	/* keep this last (previous + 1) */ +	SDEB_I_ERASE = 38, +	SDEB_I_LAST_ELEM_P1 = 39,	/* keep this last (previous + 1) */  }; @@ -530,7 +540,7 @@ static const unsigned char opcode_ind_arr[256] = {  	SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,  	SDEB_I_WRITE_FILEMARKS, SDEB_I_SPACE, SDEB_I_INQUIRY, 0, 0,  	    SDEB_I_MODE_SELECT, SDEB_I_RESERVE, SDEB_I_RELEASE, -	0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG, +	0, SDEB_I_ERASE, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,  	    SDEB_I_ALLOW_REMOVAL, 0,  /* 0x20; 0x20->0x3f: 10 byte cdbs */  	0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0, @@ -585,7 +595,9 @@ static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_read_tape(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_write_tape(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_write_scat(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *); @@ -613,8 +625,10 @@ static int resp_read_blklimits(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_locate(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_write_filemarks(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_space(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_read_position(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_rewind(struct scsi_cmnd *, struct sdebug_dev_info *);  static int resp_format_medium(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_erase(struct scsi_cmnd *, struct sdebug_dev_info *);  static int sdebug_do_add_host(bool mk_new_store);  static int sdebug_add_host_helper(int per_host_idx); @@ -629,113 +643,121 @@ static void sdebug_erase_all_stores(bool apart_from_first);   * should be placed in opcode_info_arr[], the others should be placed here.   */  static const struct opcode_info_t msense_iarr[] = { -	{0, 0x1a, 0, F_D_IN, NULL, NULL, +	{0, 0x1a, 0, DS_ALL, F_D_IN, NULL, NULL,  	    {6,  0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  };  static const struct opcode_info_t mselect_iarr[] = { -	{0, 0x15, 0, F_D_OUT, NULL, NULL, +	{0, 0x15, 0, DS_ALL, F_D_OUT, NULL, NULL,  	    {6,  0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  };  static const struct opcode_info_t read_iarr[] = { -	{0, 0x28, 0, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL,/* READ(10) */ +	{0, 0x28, 0, DS_NO_SSC, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL,/* READ(10) */  	    {10,  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,  	     0, 0, 0, 0} }, -	{0, 0x8, 0, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL, /* READ(6) */ +	{0, 0x8, 0, DS_NO_SSC, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL, /* READ(6) disk */  	    {6,  0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0xa8, 0, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL,/* READ(12) */ +	{0, 0x8, 0, DS_SSC, F_D_IN | FF_MEDIA_IO, resp_read_tape, NULL, /* READ(6) tape */ +	    {6,  0x03, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +	{0, 0xa8, 0, DS_NO_SSC, F_D_IN | FF_MEDIA_IO, resp_read_dt0, NULL,/* READ(12) */  	    {12,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf,  	     0xc7, 0, 0, 0, 0} },  };  static const struct opcode_info_t write_iarr[] = { -	{0, 0x2a, 0, F_D_OUT | FF_MEDIA_IO, resp_write_dt0,  /* WRITE(10) */ +	{0, 0x2a, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO, resp_write_dt0,  /* WRITE(10) */  	    NULL, {10,  0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7,  		   0, 0, 0, 0, 0, 0} }, -	{0, 0xa, 0, F_D_OUT | FF_MEDIA_IO, resp_write_dt0,   /* WRITE(6) */ +	{0, 0xa, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO, resp_write_dt0, /* WRITE(6) disk */  	    NULL, {6,  0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0,  		   0, 0, 0} }, -	{0, 0xaa, 0, F_D_OUT | FF_MEDIA_IO, resp_write_dt0,  /* WRITE(12) */ +	{0, 0xa, 0, DS_SSC, F_D_OUT | FF_MEDIA_IO, resp_write_tape, /* WRITE(6) tape */ +	    NULL, {6,  0x01, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, +		   0, 0, 0} }, +	{0, 0xaa, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO, resp_write_dt0,  /* WRITE(12) */  	    NULL, {12,  0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		   0xbf, 0xc7, 0, 0, 0, 0} },  };  static const struct opcode_info_t verify_iarr[] = { -	{0, 0x2f, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify,/* VERIFY(10) */ +	{0, 0x2f, 0, DS_NO_SSC, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify,/* VERIFY(10) */  	    NULL, {10,  0xf7, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xc7,  		   0, 0, 0, 0, 0, 0} },  };  static const struct opcode_info_t sa_in_16_iarr[] = { -	{0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL, +	{0, 0x9e, 0x12, DS_NO_SSC, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,  	    {16,  0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0xff, 0xff, 0, 0xc7} },	/* GET LBA STATUS(16) */ -	{0, 0x9e, 0x16, F_SA_LOW | F_D_IN, resp_get_stream_status, NULL, +	{0, 0x9e, 0x16, DS_NO_SSC, F_SA_LOW | F_D_IN, resp_get_stream_status, NULL,  	    {16, 0x16, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff,  	     0, 0} },	/* GET STREAM STATUS */  };  static const struct opcode_info_t vl_iarr[] = {	/* VARIABLE LENGTH */ -	{0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_MEDIA_IO, resp_write_dt0, +	{0, 0x7f, 0xb, DS_NO_SSC, F_SA_HIGH | F_D_OUT | FF_MEDIA_IO, resp_write_dt0,  	    NULL, {32,  0xc7, 0, 0, 0, 0, 0x3f, 0x18, 0x0, 0xb, 0xfa,  		   0, 0xff, 0xff, 0xff, 0xff} },	/* WRITE(32) */ -	{0, 0x7f, 0x11, F_SA_HIGH | F_D_OUT | FF_MEDIA_IO, resp_write_scat, +	{0, 0x7f, 0x11, DS_NO_SSC, F_SA_HIGH | F_D_OUT | FF_MEDIA_IO, resp_write_scat,  	    NULL, {32,  0xc7, 0, 0, 0, 0, 0x3f, 0x18, 0x0, 0x11, 0xf8,  		   0, 0xff, 0xff, 0x0, 0x0} },	/* WRITE SCATTERED(32) */  };  static const struct opcode_info_t maint_in_iarr[] = {	/* MAINT IN */ -	{0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL, +	{0, 0xa3, 0xc, DS_ALL, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,  	    {12,  0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,  	     0xc7, 0, 0, 0, 0} }, /* REPORT SUPPORTED OPERATION CODES */ -	{0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL, +	{0, 0xa3, 0xd, DS_ALL, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,  	    {12,  0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,  	     0, 0} },	/* REPORTED SUPPORTED TASK MANAGEMENT FUNCTIONS */  };  static const struct opcode_info_t write_same_iarr[] = { -	{0, 0x93, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_write_same_16, NULL, +	{0, 0x93, 0, DS_NO_SSC, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_write_same_16, NULL,  	    {16,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0xff, 0xff, 0x3f, 0xc7} },		/* WRITE SAME(16) */  };  static const struct opcode_info_t reserve_iarr[] = { -	{0, 0x16, 0, F_D_OUT, NULL, NULL,		/* RESERVE(6) */ +	{0, 0x16, 0, DS_ALL, F_D_OUT, NULL, NULL,	/* RESERVE(6) */  	    {6,  0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  };  static const struct opcode_info_t release_iarr[] = { -	{0, 0x17, 0, F_D_OUT, NULL, NULL,		/* RELEASE(6) */ +	{0, 0x17, 0, DS_ALL, F_D_OUT, NULL, NULL,	/* RELEASE(6) */  	    {6,  0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  };  static const struct opcode_info_t sync_cache_iarr[] = { -	{0, 0x91, 0, F_SYNC_DELAY | F_M_ACCESS, resp_sync_cache, NULL, +	{0, 0x91, 0, DS_NO_SSC, F_SYNC_DELAY | F_M_ACCESS, resp_sync_cache, NULL,  	    {16,  0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} },	/* SYNC_CACHE (16) */  };  static const struct opcode_info_t pre_fetch_iarr[] = { -	{0, 0x90, 0, F_SYNC_DELAY | FF_MEDIA_IO, resp_pre_fetch, NULL, +	{0, 0x90, 0, DS_NO_SSC, F_SYNC_DELAY | FF_MEDIA_IO, resp_pre_fetch, NULL,  	    {16,  0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} },	/* PRE-FETCH (16) */ +	{0, 0x34, 0, DS_SSC, F_SYNC_DELAY | FF_MEDIA_IO, resp_read_position, NULL, +	    {10,  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc7, 0, 0, +	     0, 0, 0, 0} },				/* READ POSITION (10) */  };  static const struct opcode_info_t zone_out_iarr[] = {	/* ZONE OUT(16) */ -	{0, 0x94, 0x1, F_SA_LOW | F_M_ACCESS, resp_close_zone, NULL, +	{0, 0x94, 0x1, DS_NO_SSC, F_SA_LOW | F_M_ACCESS, resp_close_zone, NULL,  	    {16, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} },	/* CLOSE ZONE */ -	{0, 0x94, 0x2, F_SA_LOW | F_M_ACCESS, resp_finish_zone, NULL, +	{0, 0x94, 0x2, DS_NO_SSC, F_SA_LOW | F_M_ACCESS, resp_finish_zone, NULL,  	    {16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} },	/* FINISH ZONE */ -	{0, 0x94, 0x4, F_SA_LOW | F_M_ACCESS, resp_rwp_zone, NULL, +	{0, 0x94, 0x4, DS_NO_SSC, F_SA_LOW | F_M_ACCESS, resp_rwp_zone, NULL,  	    {16, 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} },  /* RESET WRITE POINTER */  };  static const struct opcode_info_t zone_in_iarr[] = {	/* ZONE IN(16) */ -	{0, 0x95, 0x6, F_SA_LOW | F_D_IN | F_M_ACCESS, NULL, NULL, +	{0, 0x95, 0x6, DS_NO_SSC, F_SA_LOW | F_D_IN | F_M_ACCESS, NULL, NULL,  	    {16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  	     0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* REPORT ZONES */  }; @@ -746,130 +768,132 @@ static const struct opcode_info_t zone_in_iarr[] = {	/* ZONE IN(16) */   * REPORT SUPPORTED OPERATION CODES. */  static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {  /* 0 */ -	{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,	/* unknown opcodes */ +	{0, 0, 0, DS_ALL, F_INV_OP | FF_RESPOND, NULL, NULL,	/* unknown opcodes */  	    {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL, /* INQUIRY */ +	{0, 0x12, 0, DS_ALL, FF_RESPOND | F_D_IN, resp_inquiry, NULL, /* INQUIRY */  	    {6,  0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL, +	{0, 0xa0, 0, DS_ALL, FF_RESPOND | F_D_IN, resp_report_luns, NULL,  	    {12,  0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,  	     0, 0} },					/* REPORT LUNS */ -	{0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL, +	{0, 0x3, 0, DS_ALL, FF_RESPOND | F_D_IN, resp_requests, NULL,  	    {6,  0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */ +	{0, 0x0, 0, DS_ALL, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */  	    {6,  0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  /* 5 */ -	{ARRAY_SIZE(msense_iarr), 0x5a, 0, F_D_IN,	/* MODE SENSE(10) */ +	{ARRAY_SIZE(msense_iarr), 0x5a, 0, DS_ALL, F_D_IN,	/* MODE SENSE(10) */  	    resp_mode_sense, msense_iarr, {10,  0xf8, 0xff, 0xff, 0, 0, 0,  		0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, -	{ARRAY_SIZE(mselect_iarr), 0x55, 0, F_D_OUT,	/* MODE SELECT(10) */ +	{ARRAY_SIZE(mselect_iarr), 0x55, 0, DS_ALL, F_D_OUT,	/* MODE SELECT(10) */  	    resp_mode_select, mselect_iarr, {10,  0xf1, 0, 0, 0, 0, 0, 0xff,  		0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, -	{0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,	/* LOG SENSE */ +	{0, 0x4d, 0, DS_NO_SSC, F_D_IN, resp_log_sense, NULL,	/* LOG SENSE */  	    {10,  0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,  	     0, 0, 0} }, -	{0, 0x25, 0, F_D_IN, resp_readcap, NULL,    /* READ CAPACITY(10) */ +	{0, 0x25, 0, DS_NO_SSC, F_D_IN, resp_readcap, NULL,    /* READ CAPACITY(10) */  	    {10,  0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,  	     0, 0} }, -	{ARRAY_SIZE(read_iarr), 0x88, 0, F_D_IN | FF_MEDIA_IO, /* READ(16) */ +	{ARRAY_SIZE(read_iarr), 0x88, 0, DS_NO_SSC, F_D_IN | FF_MEDIA_IO, /* READ(16) */  	    resp_read_dt0, read_iarr, {16,  0xfe, 0xff, 0xff, 0xff, 0xff,  	    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7} },  /* 10 */ -	{ARRAY_SIZE(write_iarr), 0x8a, 0, F_D_OUT | FF_MEDIA_IO, +	{ARRAY_SIZE(write_iarr), 0x8a, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO,  	    resp_write_dt0, write_iarr,			/* WRITE(16) */  		{16,  0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7} }, -	{0, 0x1b, 0, F_SSU_DELAY, resp_start_stop, NULL,/* START STOP UNIT */ +	{0, 0x1b, 0, DS_ALL, F_SSU_DELAY, resp_start_stop, NULL,/* START STOP UNIT */  	    {6,  0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{ARRAY_SIZE(sa_in_16_iarr), 0x9e, 0x10, F_SA_LOW | F_D_IN, +	{ARRAY_SIZE(sa_in_16_iarr), 0x9e, 0x10, DS_NO_SSC, F_SA_LOW | F_D_IN,  	    resp_readcap16, sa_in_16_iarr, /* SA_IN(16), READ CAPACITY(16) */  		{16,  0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		 0xff, 0xff, 0xff, 0xff, 0x1, 0xc7} }, -	{0, 0x9f, 0x12, F_SA_LOW | F_D_OUT | FF_MEDIA_IO, resp_write_scat, +	{0, 0x9f, 0x12, DS_NO_SSC, F_SA_LOW | F_D_OUT | FF_MEDIA_IO, resp_write_scat,  	    NULL, {16,  0x12, 0xf9, 0x0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff,  	    0xff, 0xff, 0xff, 0xff, 0xc7} },  /* SA_OUT(16), WRITE SCAT(16) */ -	{ARRAY_SIZE(maint_in_iarr), 0xa3, 0xa, F_SA_LOW | F_D_IN, +	{ARRAY_SIZE(maint_in_iarr), 0xa3, 0xa, DS_ALL, F_SA_LOW | F_D_IN,  	    resp_report_tgtpgs,	/* MAINT IN, REPORT TARGET PORT GROUPS */  		maint_in_iarr, {12,  0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff,  				0xff, 0, 0xc7, 0, 0, 0, 0} },  /* 15 */ -	{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */ +	{0, 0, 0, DS_ALL, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */  	    {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{ARRAY_SIZE(verify_iarr), 0x8f, 0, +	{ARRAY_SIZE(verify_iarr), 0x8f, 0, DS_NO_SSC,  	    F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify,	/* VERIFY(16) */  	    verify_iarr, {16,  0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  			  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, -	{ARRAY_SIZE(vl_iarr), 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_MEDIA_IO, +	{ARRAY_SIZE(vl_iarr), 0x7f, 0x9, DS_NO_SSC, F_SA_HIGH | F_D_IN | FF_MEDIA_IO,  	    resp_read_dt0, vl_iarr,	/* VARIABLE LENGTH, READ(32) */  	    {32,  0xc7, 0, 0, 0, 0, 0x3f, 0x18, 0x0, 0x9, 0xfe, 0, 0xff, 0xff,  	     0xff, 0xff} }, -	{ARRAY_SIZE(reserve_iarr), 0x56, 0, F_D_OUT, +	{ARRAY_SIZE(reserve_iarr), 0x56, 0, DS_ALL, F_D_OUT,  	    NULL, reserve_iarr,	/* RESERVE(10) <no response function> */  	    {10,  0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,  	     0} }, -	{ARRAY_SIZE(release_iarr), 0x57, 0, F_D_OUT, +	{ARRAY_SIZE(release_iarr), 0x57, 0, DS_ALL, F_D_OUT,  	    NULL, release_iarr, /* RELEASE(10) <no response function> */  	    {10,  0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,  	     0} },  /* 20 */ -	{0, 0x1e, 0, 0, NULL, NULL, /* ALLOW REMOVAL */ +	{0, 0x1e, 0, DS_ALL, 0, NULL, NULL, /* ALLOW REMOVAL */  	    {6,  0, 0, 0, 0x3, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x1, 0, 0, resp_rewind, NULL, +	{0, 0x1, 0, DS_SSC, 0, resp_rewind, NULL,  	    {6,  0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */ +	{0, 0, 0, DS_NO_SSC, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */  	    {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x1d, F_D_OUT, 0, NULL, NULL,	/* SEND DIAGNOSTIC */ +	{0, 0x1d, 0, DS_ALL, F_D_OUT, NULL, NULL,      /* SEND DIAGNOSTIC */  	    {6,  0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x42, 0, F_D_OUT | FF_MEDIA_IO, resp_unmap, NULL, /* UNMAP */ +	{0, 0x42, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO, resp_unmap, NULL, /* UNMAP */  	    {10,  0x1, 0, 0, 0, 0, 0x3f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },  /* 25 */ -	{0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL, +	{0, 0x3b, 0, DS_NO_SSC, F_D_OUT_MAYBE, resp_write_buffer, NULL,  	    {10,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0,  	     0, 0, 0, 0} },			/* WRITE_BUFFER */ -	{ARRAY_SIZE(write_same_iarr), 0x41, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, +	{ARRAY_SIZE(write_same_iarr), 0x41, 0, DS_NO_SSC, F_D_OUT_MAYBE | FF_MEDIA_IO,  	    resp_write_same_10, write_same_iarr,	/* WRITE SAME(10) */  		{10,  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0,  		 0, 0, 0, 0, 0} }, -	{ARRAY_SIZE(sync_cache_iarr), 0x35, 0, F_SYNC_DELAY | F_M_ACCESS, +	{ARRAY_SIZE(sync_cache_iarr), 0x35, 0, DS_NO_SSC, F_SYNC_DELAY | F_M_ACCESS,  	    resp_sync_cache, sync_cache_iarr,  	    {10,  0x7, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,  	     0, 0, 0, 0} },			/* SYNC_CACHE (10) */ -	{0, 0x89, 0, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL, +	{0, 0x89, 0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL,  	    {16,  0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,  	     0, 0xff, 0x3f, 0xc7} },		/* COMPARE AND WRITE */ -	{ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, F_SYNC_DELAY | FF_MEDIA_IO, +	{ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, DS_NO_SSC, F_SYNC_DELAY | FF_MEDIA_IO,  	    resp_pre_fetch, pre_fetch_iarr,  	    {10,  0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,  	     0, 0, 0, 0} },			/* PRE-FETCH (10) */  						/* READ POSITION (10) */  /* 30 */ -	{ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW | F_M_ACCESS, +	{ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, DS_NO_SSC, F_SA_LOW | F_M_ACCESS,  	    resp_open_zone, zone_out_iarr, /* ZONE_OUT(16), OPEN ZONE) */  		{16,  0x3 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x1, 0xc7} }, -	{ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, F_SA_LOW | F_M_ACCESS, +	{ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, DS_NO_SSC, F_SA_LOW | F_M_ACCESS,  	    resp_report_zones, zone_in_iarr, /* ZONE_IN(16), REPORT ZONES) */  		{16,  0x0 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xc7} },  /* 32 */ -	{0, 0x0, 0x0, F_D_OUT | FF_MEDIA_IO, +	{0, 0x9c, 0x0, DS_NO_SSC, F_D_OUT | FF_MEDIA_IO,  	    resp_atomic_write, NULL, /* ATOMIC WRITE 16 */  		{16,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }, -	{0, 0x05, 0, F_D_IN, resp_read_blklimits, NULL,    /* READ BLOCK LIMITS (6) */ +	{0, 0x05, 0, DS_SSC, F_D_IN, resp_read_blklimits, NULL,    /* READ BLOCK LIMITS (6) */  	    {6,  0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x2b, 0, F_D_UNKN, resp_locate, NULL,    /* LOCATE (10) */ +	{0, 0x2b, 0, DS_SSC, F_D_UNKN, resp_locate, NULL,	   /* LOCATE (10) */  	    {10,  0x07, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xc7, 0, 0,  	     0, 0, 0, 0} }, -	{0, 0x10, 0, F_D_IN, resp_write_filemarks, NULL,    /* WRITE FILEMARKS (6) */ +	{0, 0x10, 0, DS_SSC, F_D_IN, resp_write_filemarks, NULL,   /* WRITE FILEMARKS (6) */  	    {6,  0x01, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x11, 0, F_D_IN, resp_space, NULL,    /* SPACE (6) */ +	{0, 0x11, 0, DS_SSC, F_D_IN, resp_space, NULL,    /* SPACE (6) */  	    {6,  0x07, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -	{0, 0x4, 0, 0, resp_format_medium, NULL,  /* FORMAT MEDIUM (6) */ +	{0, 0x4, 0, DS_SSC, 0, resp_format_medium, NULL,  /* FORMAT MEDIUM (6) */  	    {6,  0x3, 0x7, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, -/* 38 */ +	{0, 0x19, 0, DS_SSC, F_D_IN, resp_erase, NULL,    /* ERASE (6) */ +	    {6,  0x03, 0x33, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +/* 39 */  /* sentinel */ -	{0xff, 0, 0, 0, NULL, NULL,		/* terminating element */ +	{0xff, 0, 0, 0, 0, NULL, NULL,		/* terminating element */  	    {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },  }; @@ -1015,6 +1039,19 @@ static const int condition_met_result = SAM_STAT_CONDITION_MET;  static struct dentry *sdebug_debugfs_root;  static ASYNC_DOMAIN_EXCLUSIVE(sdebug_async_domain); +static u32 sdebug_get_devsel(struct scsi_device *sdp) +{ +	unsigned char devtype = sdp->type; +	u32 devsel; + +	if (devtype < 32) +		devsel = (1 << devtype); +	else +		devsel = DS_ALL; + +	return devsel; +} +  static void sdebug_err_free(struct rcu_head *head)  {  	struct sdebug_err_inject *inject = @@ -2032,13 +2069,19 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	unsigned char *cmd = scp->cmnd;  	u32 alloc_len, n;  	int ret; -	bool have_wlun, is_disk, is_zbc, is_disk_zbc; +	bool have_wlun, is_disk, is_zbc, is_disk_zbc, is_tape;  	alloc_len = get_unaligned_be16(cmd + 3);  	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);  	if (! arr)  		return DID_REQUEUE << 16; -	is_disk = (sdebug_ptype == TYPE_DISK); +	if (scp->device->type >= 32) { +		is_disk = (sdebug_ptype == TYPE_DISK); +		is_tape = (sdebug_ptype == TYPE_TAPE); +	} else { +		is_disk = (scp->device->type == TYPE_DISK); +		is_tape = (scp->device->type == TYPE_TAPE); +	}  	is_zbc = devip->zoned;  	is_disk_zbc = (is_disk || is_zbc);  	have_wlun = scsi_is_wlun(scp->device->lun); @@ -2047,7 +2090,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	else if (sdebug_no_lun_0 && (devip->lun == SDEBUG_LUN_0_VAL))  		pq_pdt = 0x7f;	/* not present, PQ=3, PDT=0x1f */  	else -		pq_pdt = (sdebug_ptype & 0x1f); +		pq_pdt = ((scp->device->type >= 32 ? +				sdebug_ptype : scp->device->type) & 0x1f);  	arr[0] = pq_pdt;  	if (0x2 & cmd[1]) {  /* CMDDT bit set */  		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1); @@ -2170,7 +2214,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	if (is_disk) {		/* SBC-4 no version claimed */  		put_unaligned_be16(0x600, arr + n);  		n += 2; -	} else if (sdebug_ptype == TYPE_TAPE) {	/* SSC-4 rev 3 */ +	} else if (is_tape) {	/* SSC-4 rev 3 */  		put_unaligned_be16(0x525, arr + n);  		n += 2;  	} else if (is_zbc) {	/* ZBC BSR INCITS 536 revision 05 */ @@ -2279,7 +2323,7 @@ static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	changing = (stopped_state != want_stop);  	if (changing)  		atomic_xchg(&devip->stopped, want_stop); -	if (sdebug_ptype == TYPE_TAPE && !want_stop) { +	if (scp->device->type == TYPE_TAPE && !want_stop) {  		int i;  		set_bit(SDEBUG_UA_NOT_READY_TO_READY, devip->uas_bm); /* not legal! */ @@ -2454,11 +2498,12 @@ static int resp_rsup_opcodes(struct scsi_cmnd *scp,  	u8 reporting_opts, req_opcode, sdeb_i, supp;  	u16 req_sa, u;  	u32 alloc_len, a_len; -	int k, offset, len, errsts, count, bump, na; +	int k, offset, len, errsts, bump, na;  	const struct opcode_info_t *oip;  	const struct opcode_info_t *r_oip;  	u8 *arr;  	u8 *cmd = scp->cmnd; +	u32 devsel = sdebug_get_devsel(scp->device);  	rctd = !!(cmd[2] & 0x80);  	reporting_opts = cmd[2] & 0x7; @@ -2481,34 +2526,30 @@ static int resp_rsup_opcodes(struct scsi_cmnd *scp,  	}  	switch (reporting_opts) {  	case 0:	/* all commands */ -		/* count number of commands */ -		for (count = 0, oip = opcode_info_arr; -		     oip->num_attached != 0xff; ++oip) { -			if (F_INV_OP & oip->flags) -				continue; -			count += (oip->num_attached + 1); -		}  		bump = rctd ? 20 : 8; -		put_unaligned_be32(count * bump, arr);  		for (offset = 4, oip = opcode_info_arr;  		     oip->num_attached != 0xff && offset < a_len; ++oip) {  			if (F_INV_OP & oip->flags)  				continue; +			if ((devsel & oip->devsel) != 0) { +				arr[offset] = oip->opcode; +				put_unaligned_be16(oip->sa, arr + offset + 2); +				if (rctd) +					arr[offset + 5] |= 0x2; +				if (FF_SA & oip->flags) +					arr[offset + 5] |= 0x1; +				put_unaligned_be16(oip->len_mask[0], arr + offset + 6); +				if (rctd) +					put_unaligned_be16(0xa, arr + offset + 8); +				offset += bump; +			}  			na = oip->num_attached; -			arr[offset] = oip->opcode; -			put_unaligned_be16(oip->sa, arr + offset + 2); -			if (rctd) -				arr[offset + 5] |= 0x2; -			if (FF_SA & oip->flags) -				arr[offset + 5] |= 0x1; -			put_unaligned_be16(oip->len_mask[0], arr + offset + 6); -			if (rctd) -				put_unaligned_be16(0xa, arr + offset + 8);  			r_oip = oip;  			for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {  				if (F_INV_OP & oip->flags)  					continue; -				offset += bump; +				if ((devsel & oip->devsel) == 0) +					continue;  				arr[offset] = oip->opcode;  				put_unaligned_be16(oip->sa, arr + offset + 2);  				if (rctd) @@ -2516,14 +2557,15 @@ static int resp_rsup_opcodes(struct scsi_cmnd *scp,  				if (FF_SA & oip->flags)  					arr[offset + 5] |= 0x1;  				put_unaligned_be16(oip->len_mask[0], -						   arr + offset + 6); +						arr + offset + 6);  				if (rctd)  					put_unaligned_be16(0xa,  							   arr + offset + 8); +				offset += bump;  			}  			oip = r_oip; -			offset += bump;  		} +		put_unaligned_be32(offset - 4, arr);  		break;  	case 1:	/* one command: opcode only */  	case 2:	/* one command: opcode plus service action */ @@ -2549,13 +2591,15 @@ static int resp_rsup_opcodes(struct scsi_cmnd *scp,  				return check_condition_result;  			}  			if (0 == (FF_SA & oip->flags) && -			    req_opcode == oip->opcode) +				(devsel & oip->devsel) != 0 && +				req_opcode == oip->opcode)  				supp = 3;  			else if (0 == (FF_SA & oip->flags)) {  				na = oip->num_attached;  				for (k = 0, oip = oip->arrp; k < na;  				     ++k, ++oip) { -					if (req_opcode == oip->opcode) +					if (req_opcode == oip->opcode && +						(devsel & oip->devsel) != 0)  						break;  				}  				supp = (k >= na) ? 1 : 3; @@ -2563,7 +2607,8 @@ static int resp_rsup_opcodes(struct scsi_cmnd *scp,  				na = oip->num_attached;  				for (k = 0, oip = oip->arrp; k < na;  				     ++k, ++oip) { -					if (req_sa == oip->sa) +					if (req_sa == oip->sa && +						(devsel & oip->devsel) != 0)  						break;  				}  				supp = (k >= na) ? 1 : 3; @@ -2914,9 +2959,9 @@ static int resp_mode_sense(struct scsi_cmnd *scp,  	subpcode = cmd[3];  	msense_6 = (MODE_SENSE == cmd[0]);  	llbaa = msense_6 ? false : !!(cmd[1] & 0x10); -	is_disk = (sdebug_ptype == TYPE_DISK); +	is_disk = (scp->device->type == TYPE_DISK);  	is_zbc = devip->zoned; -	is_tape = (sdebug_ptype == TYPE_TAPE); +	is_tape = (scp->device->type == TYPE_TAPE);  	if ((is_disk || is_zbc || is_tape) && !dbd)  		bd_len = llbaa ? 16 : 8;  	else @@ -3131,7 +3176,7 @@ static int resp_mode_select(struct scsi_cmnd *scp,  	md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2);  	bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6);  	off = (mselect6 ? 4 : 8); -	if (sdebug_ptype == TYPE_TAPE) { +	if (scp->device->type == TYPE_TAPE) {  		int blksize;  		if (bd_len != 8) { @@ -3196,7 +3241,7 @@ static int resp_mode_select(struct scsi_cmnd *scp,  		}  		break;  	case 0xf:       /* Compression mode page */ -		if (sdebug_ptype != TYPE_TAPE) +		if (scp->device->type != TYPE_TAPE)  			goto bad_pcode;  		if ((arr[off + 2] & 0x40) != 0) {  			devip->tape_dce = (arr[off + 2] & 0x80) != 0; @@ -3204,7 +3249,7 @@ static int resp_mode_select(struct scsi_cmnd *scp,  		}  		break;  	case 0x11:	/* Medium Partition Mode Page (tape) */ -		if (sdebug_ptype == TYPE_TAPE) { +		if (scp->device->type == TYPE_TAPE) {  			int fld;  			fld = process_medium_part_m_pg(devip, &arr[off], pg_len); @@ -3563,6 +3608,30 @@ is_eop:  	return check_condition_result;  } +enum {SDEBUG_READ_POSITION_ARR_SZ = 20}; +static int resp_read_position(struct scsi_cmnd *scp, +			struct sdebug_dev_info *devip) +{ +	u8 *cmd = scp->cmnd; +	int all_length; +	unsigned char arr[20]; +	unsigned int pos; + +	all_length = get_unaligned_be16(cmd + 7); +	if ((cmd[1] & 0xfe) != 0 || +		all_length != 0) { /* only short form */ +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, +				all_length ? 7 : 1, 0); +		return check_condition_result; +	} +	memset(arr, 0, SDEBUG_READ_POSITION_ARR_SZ); +	arr[1] = devip->tape_partition; +	pos = devip->tape_location[devip->tape_partition]; +	put_unaligned_be32(pos, arr + 4); +	put_unaligned_be32(pos, arr + 8); +	return fill_from_dev_buffer(scp, arr, SDEBUG_READ_POSITION_ARR_SZ); +} +  static int resp_rewind(struct scsi_cmnd *scp,  		struct sdebug_dev_info *devip)  { @@ -3604,10 +3673,6 @@ static int resp_format_medium(struct scsi_cmnd *scp,  	int res = 0;  	unsigned char *cmd = scp->cmnd; -	if (sdebug_ptype != TYPE_TAPE) { -		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 0, -1); -		return check_condition_result; -	}  	if (cmd[2] > 2) {  		mk_sense_invalid_fld(scp, SDEB_IN_DATA, 2, -1);  		return check_condition_result; @@ -3631,6 +3696,19 @@ static int resp_format_medium(struct scsi_cmnd *scp,  	return 0;  } +static int resp_erase(struct scsi_cmnd *scp, +		struct sdebug_dev_info *devip) +{ +	int partition = devip->tape_partition; +	int pos = devip->tape_location[partition]; +	struct tape_block *blp; + +	blp = devip->tape_blocks[partition] + pos; +	blp->fl_size = TAPE_BLOCK_EOD_FLAG; + +	return 0; +} +  static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip)  {  	return devip->nr_zones != 0; @@ -4467,9 +4545,6 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	u8 *cmd = scp->cmnd;  	bool meta_data_locked = false; -	if (sdebug_ptype == TYPE_TAPE) -		return resp_read_tape(scp, devip); -  	switch (cmd[0]) {  	case READ_16:  		ei_lba = 0; @@ -4839,9 +4914,6 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)  	u8 *cmd = scp->cmnd;  	bool meta_data_locked = false; -	if (sdebug_ptype == TYPE_TAPE) -		return resp_write_tape(scp, devip); -  	switch (cmd[0]) {  	case WRITE_16:  		ei_lba = 0; @@ -5573,7 +5645,6 @@ static int resp_sync_cache(struct scsi_cmnd *scp,   *   * The pcode 0x34 is also used for READ POSITION by tape devices.   */ -enum {SDEBUG_READ_POSITION_ARR_SZ = 20};  static int resp_pre_fetch(struct scsi_cmnd *scp,  			  struct sdebug_dev_info *devip)  { @@ -5585,31 +5656,6 @@ static int resp_pre_fetch(struct scsi_cmnd *scp,  	struct sdeb_store_info *sip = devip2sip(devip, true);  	u8 *fsp = sip->storep; -	if (sdebug_ptype == TYPE_TAPE) { -		if (cmd[0] == PRE_FETCH) { /* READ POSITION (10) */ -			int all_length; -			unsigned char arr[20]; -			unsigned int pos; - -			all_length = get_unaligned_be16(cmd + 7); -			if ((cmd[1] & 0xfe) != 0 || -				all_length != 0) { /* only short form */ -				mk_sense_invalid_fld(scp, SDEB_IN_CDB, -						all_length ? 7 : 1, 0); -				return check_condition_result; -			} -			memset(arr, 0, SDEBUG_READ_POSITION_ARR_SZ); -			arr[1] = devip->tape_partition; -			pos = devip->tape_location[devip->tape_partition]; -			put_unaligned_be32(pos, arr + 4); -			put_unaligned_be32(pos, arr + 8); -			return fill_from_dev_buffer(scp, arr, -						SDEBUG_READ_POSITION_ARR_SZ); -		} -		mk_sense_invalid_opcode(scp); -		return check_condition_result; -	} -  	if (cmd[0] == PRE_FETCH) {	/* 10 byte cdb */  		lba = get_unaligned_be32(cmd + 2);  		nblks = get_unaligned_be16(cmd + 7); @@ -6645,7 +6691,7 @@ static void scsi_debug_sdev_destroy(struct scsi_device *sdp)  	debugfs_remove(devip->debugfs_entry); -	if (sdebug_ptype == TYPE_TAPE) { +	if (sdp->type == TYPE_TAPE) {  		kfree(devip->tape_blocks[0]);  		devip->tape_blocks[0] = NULL;  	} @@ -6833,18 +6879,16 @@ static int sdebug_fail_lun_reset(struct scsi_cmnd *cmnd)  static void scsi_tape_reset_clear(struct sdebug_dev_info *devip)  { -	if (sdebug_ptype == TYPE_TAPE) { -		int i; +	int i; -		devip->tape_blksize = TAPE_DEF_BLKSIZE; -		devip->tape_density = TAPE_DEF_DENSITY; -		devip->tape_partition = 0; -		devip->tape_dce = 0; -		for (i = 0; i < TAPE_MAX_PARTITIONS; i++) -			devip->tape_location[i] = 0; -		devip->tape_pending_nbr_partitions = -1; -		/* Don't reset partitioning? */ -	} +	devip->tape_blksize = TAPE_DEF_BLKSIZE; +	devip->tape_density = TAPE_DEF_DENSITY; +	devip->tape_partition = 0; +	devip->tape_dce = 0; +	for (i = 0; i < TAPE_MAX_PARTITIONS; i++) +		devip->tape_location[i] = 0; +	devip->tape_pending_nbr_partitions = -1; +	/* Don't reset partitioning? */  }  static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt) @@ -6862,7 +6906,8 @@ static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt)  	scsi_debug_stop_all_queued(sdp);  	if (devip) {  		set_bit(SDEBUG_UA_POR, devip->uas_bm); -		scsi_tape_reset_clear(devip); +		if (SCpnt->device->type == TYPE_TAPE) +			scsi_tape_reset_clear(devip);  	}  	if (sdebug_fail_lun_reset(SCpnt)) { @@ -6901,7 +6946,8 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)  	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {  		if (devip->target == sdp->id) {  			set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); -			scsi_tape_reset_clear(devip); +			if (SCpnt->device->type == TYPE_TAPE) +				scsi_tape_reset_clear(devip);  			++k;  		}  	} @@ -6933,7 +6979,8 @@ static int scsi_debug_bus_reset(struct scsi_cmnd *SCpnt)  	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {  		set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); -		scsi_tape_reset_clear(devip); +		if (SCpnt->device->type == TYPE_TAPE) +			scsi_tape_reset_clear(devip);  		++k;  	} @@ -6957,7 +7004,8 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt)  		list_for_each_entry(devip, &sdbg_host->dev_info_list,  				    dev_list) {  			set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); -			scsi_tape_reset_clear(devip); +			if (SCpnt->device->type == TYPE_TAPE) +				scsi_tape_reset_clear(devip);  			++k;  		}  	} @@ -9173,6 +9221,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,  	u32 flags;  	u16 sa;  	u8 opcode = cmd[0]; +	u32 devsel = sdebug_get_devsel(scp->device);  	bool has_wlun_rl;  	bool inject_now;  	int ret = 0; @@ -9252,12 +9301,14 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,  			else  				sa = get_unaligned_be16(cmd + 8);  			for (k = 0; k <= na; oip = r_oip->arrp + k++) { -				if (opcode == oip->opcode && sa == oip->sa) +				if (opcode == oip->opcode && sa == oip->sa && +					(devsel & oip->devsel) != 0)  					break;  			}  		} else {   /* since no service action only check opcode */  			for (k = 0; k <= na; oip = r_oip->arrp + k++) { -				if (opcode == oip->opcode) +				if (opcode == oip->opcode && +					(devsel & oip->devsel) != 0)  					break;  			}  		}  | 
