All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi_debug 2.6.9-rc1
@ 2004-08-29 13:06 Douglas Gilbert
  0 siblings, 0 replies; only message in thread
From: Douglas Gilbert @ 2004-08-29 13:06 UTC (permalink / raw)
  To: linux-scsi; +Cc: James.Bottomley

[-- Attachment #1: Type: text/plain, Size: 606 bytes --]

To check descriptor format sense data handling we need a source.
Clean up some other problems and improve support for st.

Changes:
   - add 'dsense' option to generate descriptor sense data
     format (default still fixed format)
   - correct unit attention generation (only INQUIRY, REQUEST_SENSE
     and REPORT_LUNS ignore it)
   - better information sent to log in "noisy" mode (i.e. opts=1)
   - correct and expand standard INQUIRY response, include version
     descriptors
   - filter MODE_SENSE command so that subpage!=0 generates error
   - add REWIND (SSC) command support (NOP)

Doug Gilbert

[-- Attachment #2: sdebug269rc1_174.diff --]
[-- Type: text/x-patch, Size: 10440 bytes --]

--- linux/drivers/scsi/scsi_debug.c	2004-08-14 21:12:43.000000000 +1000
+++ linux/drivers/scsi/scsi_debug.c269rc1_174	2004-08-29 22:36:05.000000000 +1000
@@ -55,8 +55,8 @@
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-#define SCSI_DEBUG_VERSION "1.73"
-static const char * scsi_debug_version_date = "20040518";
+#define SCSI_DEBUG_VERSION "1.74"
+static const char * scsi_debug_version_date = "20040829";
 
 /* Additional Sense Code (ASC) used */
 #define NO_ADDED_SENSE 0x0
@@ -82,8 +82,9 @@
 #define DEF_EVERY_NTH   0
 #define DEF_NUM_PARTS   0
 #define DEF_OPTS   0
-#define DEF_SCSI_LEVEL   3
+#define DEF_SCSI_LEVEL   4    /* SPC-2 */
 #define DEF_PTYPE   0
+#define DEF_D_SENSE   0
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -114,6 +115,7 @@
 static int scsi_debug_opts = DEF_OPTS;
 static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
 static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
+static int scsi_debug_dsense = DEF_D_SENSE;
 
 static int scsi_debug_cmnd_count = 0;
 
@@ -277,7 +279,7 @@
 int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 {
 	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
-	int block, upper_blk, num;
+	int block, upper_blk, num, k;
 	unsigned char *buff;
 	int errsts = 0;
 	int target = SCpnt->device->id;
@@ -305,7 +307,12 @@
 		bufflen = SDEBUG_SENSE_LEN;
 	}
 
-
+	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
+		printk(KERN_INFO "scsi_debug: cmd ");
+		for (k = 0, num = SCpnt->cmd_len; k < num; ++k)
+			printk("%02x ", (int)cmd[k]);
+		printk("\n");
+	}
         if(target == sdebug_driver_template.this_id) {
 		printk(KERN_INFO "scsi_debug: initiator's id used as "
 		       "target!\n");
@@ -331,14 +338,10 @@
         }
 
 	switch (*cmd) {
-	case INQUIRY:     /* mandatory */
+	case INQUIRY:     /* mandatory, ignore unit attention */
 		errsts = resp_inquiry(cmd, target, buff, bufflen, devip);
 		break;
-	case REQUEST_SENSE:	/* mandatory */
-		/* Since this driver indicates autosense by placing the
-		 * sense buffer in the scsi_cmnd structure in the response
-		 * (when SAM_STAT_CHECK_CONDITION is set), the mid level
-		 * shouldn't need to call REQUEST_SENSE */
+	case REQUEST_SENSE:	/* mandatory, ignore unit attention */
 		if (devip) {
 			sbuff = devip->sense_buff;
 			memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
@@ -349,20 +352,24 @@
 			buff[0] = 0x70;
 		}
 		break;
+	case REZERO_UNIT:	/* actually this is REWIND for SSC */
 	case START_STOP:
 		errsts = check_reset(SCpnt, devip);
+		memset(buff, 0, bufflen);
 		break;
 	case ALLOW_MEDIUM_REMOVAL:
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk("\tMedium removal %s\n",
-			       cmd[4] ? "inhibited" : "enabled");
+			printk(KERN_INFO "scsi_debug: Medium removal %s\n",
+			        cmd[4] ? "inhibited" : "enabled");
 		break;
 	case SEND_DIAGNOSTIC:     /* mandatory */
+		errsts = check_reset(SCpnt, devip);
 		memset(buff, 0, bufflen);
 		break;
 	case TEST_UNIT_READY:     /* mandatory */
+		errsts = check_reset(SCpnt, devip);
 		memset(buff, 0, bufflen);
 		break;
         case RESERVE:
@@ -429,7 +436,7 @@
 			errsts = check_condition_result;
 		}
 		break;
-	case REPORT_LUNS:
+	case REPORT_LUNS:	/* mandatory, ignore unit attention */
 		errsts = resp_report_luns(cmd, buff, bufflen, devip);
 		break;
 	case WRITE_16:
@@ -469,14 +476,20 @@
 		break;
 	case MODE_SENSE:
 	case MODE_SENSE_10:
+		if ((errsts = check_reset(SCpnt, devip)))
+			break;
 		errsts = resp_mode_sense(cmd, target, buff, bufflen, devip);
 		break;
 	case SYNCHRONIZE_CACHE:
+		errsts = check_reset(SCpnt, devip);
 		memset(buff, 0, bufflen);
 		break;
 	default:
+		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
+			       "supported\n", *cmd);
 		if ((errsts = check_reset(SCpnt, devip)))
-			break;
+			break;	/* Unit attention takes precedence */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0, 18);
 		errsts = check_condition_result;
 		break;
@@ -496,6 +509,9 @@
 static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
 {
 	if (devip->reset) {
+		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+			printk(KERN_INFO "scsi_debug: Reporting Unit "
+			       "attention: power on reset\n");
 		devip->reset = 0;
 		mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0, 18);
 		return check_condition_result;
@@ -503,7 +519,7 @@
 	return 0;
 }
 
-#define SDEBUG_LONG_INQ_SZ 58
+#define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 128
 
 static const char * vendor_id = "Linux   ";
@@ -593,11 +609,21 @@
 	/* drops through here for a standard inquiry */
 	arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0;	/* Removable disk */
 	arr[2] = scsi_debug_scsi_level;
+	arr[3] = 2;    /* response_data_format==2 */
 	arr[4] = SDEBUG_LONG_INQ_SZ - 5;
+	arr[6] = 0x1; /* claim: ADDR16 */
 	arr[7] = 0x3a; /* claim: WBUS16, SYNC, LINKED + CMDQUE */
 	memcpy(&arr[8], vendor_id, 8);
 	memcpy(&arr[16], product_id, 16);
 	memcpy(&arr[32], product_rev, 4);
+	/* version descriptors (2 bytes each) follow */
+	arr[58] = 0x0; arr[59] = 0x40; /* SAM-2 */
+	arr[60] = 0x2; arr[61] = 0x60; /* SPC-2 */
+	if (scsi_debug_ptype == 0) {
+	    arr[62] = 0x1; arr[63] = 0x80; /* SBC */
+	} else if (scsi_debug_ptype == 1) {
+	    arr[62] = 0x2; arr[63] = 0x00; /* SSC */
+	}
 	memcpy(buff, arr, min_len);
 	return 0;
 }
@@ -660,6 +686,8 @@
 	unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
 				     0, 0, 0x2, 0x4b};
 
+	if (scsi_debug_dsense)
+		ctrl_m_pg[2] |= 0x4;
 	memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
 	if (1 == pcontrol)
 		memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
@@ -683,7 +711,7 @@
 			   struct sdebug_dev_info * devip)
 {
 	unsigned char dbd;
-	int pcontrol, pcode;
+	int pcontrol, pcode, subpcode;
 	unsigned char dev_spec;
 	int alloc_len, msense_6, offset, len;
 	unsigned char * ap;
@@ -695,11 +723,9 @@
 	dbd = cmd[1] & 0x8;
 	pcontrol = (cmd[2] & 0xc0) >> 6;
 	pcode = cmd[2] & 0x3f;
+	subpcode = cmd[3];
 	msense_6 = (MODE_SENSE == cmd[0]);
 	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
-	/* printk(KERN_INFO "msense: dbd=%d pcontrol=%d pcode=%d "
-		"msense_6=%d alloc_len=%d\n", dbd, pcontrol, pcode, "
-		"msense_6, alloc_len); */
 	if (bufflen < alloc_len)
 		printk(KERN_INFO "scsi_debug: mode_sense: bufflen=%d "
 		       "< alloc_length=%d\n", bufflen, alloc_len);
@@ -720,6 +746,11 @@
 	}
 	ap = arr + offset;
 
+	if (0 != subpcode) { /* TODO: Control Extension page */
+		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+			       	0, 18);
+		return check_condition_result;
+	}
 	switch (pcode) {
 	case 0x1:	/* Read-Write error recovery page, direct access */
 		len = resp_err_recov_pg(ap, pcontrol, target);
@@ -1023,13 +1054,23 @@
 
 	sbuff = devip->sense_buff;
 	memset(sbuff, 0, SDEBUG_SENSE_LEN);
-	if (inbandLen > SDEBUG_SENSE_LEN)
-		inbandLen = SDEBUG_SENSE_LEN;
-	sbuff[0] = 0x70;
-	sbuff[2] = key;
-	sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0;
-	sbuff[12] = asc;
-	sbuff[13] = asq;
+	if (scsi_debug_dsense) {
+		sbuff[0] = 0x72;  /* descriptor, current */
+		sbuff[1] = key;
+		sbuff[2] = asc;
+		sbuff[3] = asq;
+	} else {
+		if (inbandLen > SDEBUG_SENSE_LEN)
+			inbandLen = SDEBUG_SENSE_LEN;
+		sbuff[0] = 0x70;  /* fixed, current */
+		sbuff[2] = key;
+		sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0;
+		sbuff[12] = asc;
+		sbuff[13] = asq;
+	}
+	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+		printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
+		      "[0x%x,0x%x,0x%x]\n", key, asc, asq);
 }
 
 static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
@@ -1230,17 +1271,11 @@
 			 struct sdebug_dev_info * devip,
 			 done_funct_t done, int scsi_result, int delta_jiff)
 {
-	int k, num;
-
 	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
-		printk(KERN_INFO "scsi_debug: cmd ");
-		for (k = 0, num = cmnd->cmd_len; k < num; ++k)
-			printk("%02x ", (int)cmnd->cmnd[k]);
-		printk("\n");
 		if (scsi_result) {
 			struct scsi_device * sdp = cmnd->device;
 
-			printk(KERN_INFO "scsi_debug: ... <%u %u %u %u> "
+			printk(KERN_INFO "scsi_debug:    <%u %u %u %u> "
 			       "non-zero result=0x%x\n", sdp->host->host_no,
 			       sdp->channel, sdp->id, sdp->lun, scsi_result);
 		}
@@ -1296,6 +1331,7 @@
 module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */
 module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */
 module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0);
+module_param_named(dsense, scsi_debug_dsense, int, 0);
 module_param_named(every_nth, scsi_debug_every_nth, int, 0);
 module_param_named(max_luns, scsi_debug_max_luns, int, 0);
 module_param_named(num_parts, scsi_debug_num_parts, int, 0);
@@ -1312,13 +1348,14 @@
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
 MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
+MODULE_PARM_DESC(dsense, "use descriptor sense format(def: fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
 MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
 MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
 MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->...");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
-MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
+MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=4[SPC-2])");
 
 
 static char sdebug_info[256];
@@ -1452,6 +1489,24 @@
 }
 DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store);
 
+static ssize_t sdebug_dsense_show(struct device_driver * ddp, char * buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
+}
+static ssize_t sdebug_dsense_store(struct device_driver * ddp,
+				  const char * buf, size_t count)
+{
+        int n;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		scsi_debug_dsense = n;
+		return count;
+	}
+	return -EINVAL;
+}
+DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show,
+	    sdebug_dsense_store);
+
 static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-08-29 13:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-29 13:06 [PATCH] scsi_debug 2.6.9-rc1 Douglas Gilbert

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.